Skip to main content

useStepState

useStep 을 확장해 multi-step processstep을 관리 및 추적하며 동시에 내부 상태를 관리 할 수 있는 커스텀 훅입니다.

storageOptions를 활용해 setState 시에 브라우저 스토리지(sessionStorage, localStorage)에 상태를 저장 할 수 있습니다.

clearState는 state를 null로 초기화합니다. storageOptions가 있을 경우 해당 options에 대응하는 스토리지 데이터를 제거합니다.


Code

🔗 실제 구현 코드 확인

Interface

typescript
interface StorageOptions {
key: string;
type: 'localStorage' | 'sessionStorage';
}

interface UseStepWithInitialState<T> extends UseStepProps {
initialState: T;
storageOptions?: StorageOptions;
}

interface UseStepWithoutInitialState extends UseStepProps {
storageOptions?: StorageOptions;
}
typescript
// 함수 오버로딩
export function useStepState<T>({
initialState,
...props
}: UseStepWithInitialState<T>): ReturnType<typeof useStep> & {
readonly state: T;
readonly setState: (newState: SetStateAction<T>) => void;
readonly clearState: () => void;
};

export function useStepState<T>(props: UseStepWithoutInitialState): ReturnType<
typeof useStep
> & {
readonly state: T | null;
readonly setState: (newState: SetStateAction<T | null>) => void;
readonly clearState: () => void;
};

Usage

typescript
import { useStepState } from '@modern-kit/react';

export const Example = () => {
const { state, setState, clearState, currentStep, goToNextStep, goToPrevStep } =
useStepState({
maxStep: 2,
initialState: { name: '' },
storageOptions: { key: 'stepState', type: 'sessionStorage' },
});

const handleGoToNextStep = () => {
goToNextStep(({ prevStep, nextStep }) => {
console.log(`${prevStep}에서 ${nextStep}로 이동`);
setState({ name: 'bar' });
});
};

const handleGoToPrevStep = () => {
goToPrevStep(({ prevStep, nextStep }) => {
console.log(`${prevStep}에서 ${nextStep}로 이동`);
setState({ name: 'foo' });
});
};

const boxStyle = {
width: '300px',
height: '120px',
fontSize: '21px',
};

return (
<div>
<div>
<button onClick={handleGoToPrevStep}>이전 스탭</button>
<button onClick={handleGoToNextStep}>다음 스탭</button>
<button onClick={clearState}>상태 초기화</button>
</div>
<div>
<p>currentStep: {currentStep}</p>
<p>state: {JSON.stringify(state)}</p>
</div>
<div>
{currentStep === 1 && (
<div style={{ ...boxStyle, backgroundColor: 'red' }}>
1번 Step Box
</div>
)}
{currentStep === 2 && (
<div style={{ ...boxStyle, backgroundColor: 'green' }}>
2번 Step Box
</div>
)}
</div>
</div>
);
};

Example

currentStep: 0

state: {"name":""}


Best Practice

  • 브라우저 새로고침 시 상태를 적절하게 유지하고 싶다면 queryStringreact-router-dom을 함께 사용하는 것을 권장합니다.
import { useStepState } from '@modern-kit/react';
import { useNavigate } from 'react-router-dom'
import qs from 'query-string'

const Example = () => {
const parsedStorage = JSON.parse(sessionStorage.getItem('stepState'));
const parsedQuery = qs.parse(location.search);

const navigate = useNavigate();

const { state, setState, goToNextStep, goToPrevStep } = useStepState({
maxStep: 5,
initialState: parsedStorage,
initialStep: parsedQuery.step,
storageOptions: { key: 'stepState', type: 'sessionStorage' },
});

const handleGoToNextStep = () => {
goToNextStep(({ nextStep }) => {
setState({
/* ... */
});
navigate(`/test?step=${nextStep}`);
});
};

const handleGoToPrevStep = () => {
goToNextStep(({ nextStep }) => {
setState({
/* ... */
});
navigate(`/test?step=${nextStep}`);
});
};

// ...
return (
// ...
);
};