front_end/react
React - useReducer (in typescript)
joepasss
2022. 5. 13. 22:38
USEREDUCER
useState가 여의치 못한 상황일 때 사용 (state 종류가 많던지 등의)
reducer 함수 예시
function reducer(state: CounterState, action: CounterAction) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + action.payload };
case 'DECREMENT':
return { count: state.count - action.payload };
default:
return state;
}
}
사용 예시
import { FC, useReducer } from 'react';
type CounterState = {
count: number;
};
type CounterAction = {
type: string;
payload: number;
};
const initialState = { count: 0 };
function reducer(state: CounterState, action: CounterAction) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + action.payload };
case 'DECREMENT':
return { count: state.count - action.payload };
default:
return state;
}
}
export const Counter: FC = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div className='container'>
Count: {state.count}
<button
onClick={() => dispatch({ type: 'INCREMENT', payload: 10 })}
>
Increment 10
</button>
<button
onClick={() => dispatch({ type: 'DECREMENT', payload: 10 })}
>
DECREMENT 10
</button>
</div>
);
};
- dispatch를 통해 상태를 변화시킨다
strict action type
- Reset 추가
function reducer(state: CounterState, action: CounterAction) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + action.payload };
case 'DECREMENT':
return { count: state.count - action.payload };
case 'RESET':
return initalState;
default:
return state;
}
}
- payload가 인수로 전달되지 않아 오류가 발생하는 모습이다.
해결
- type을 두 가지로 나눈다 (UpdateAction, ResetAction)
type UpdateAction = {
type: string;
payload: number;
}
type ResetAction = {
type: string;
}
- CounterAction의 타입을 UpdateAction | ResetAction; 으로 둘 다 가능하도록 유니온 시킨다
type CounterAction = UpdateAction | ResetAction;
- ResetAction type(CounterAction 안에 포함됨)에 payload 인수가 없다는 에러가 뜬다
- UpdateAction, ResetAction 내부의 type property를 string 이 아닌 INCREMENT, DECREMENT, RESET 등으로 명시 해 준다
type UpdateAction = {
type: 'INCREMENT' | 'DECREMENT';
payload: number;
}
type ResetAction = {
type: 'RESET';
}
- 에러가 해결된 모습을 볼 수 있다
전체 코드
import { FC, useReducer } from 'react';
type CounterState = {
count: number;
};
type UpdateAction = {
type: 'INCREMENT' | 'DECREMENT';
payload: number;
};
type ResetAction = {
type: 'RESET';
};
type CounterAction = UpdateAction | ResetAction;
const initialState = { count: 0 };
function reducer(state: CounterState, action: CounterAction) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + action.payload };
case 'DECREMENT':
return { count: state.count - action.payload };
case 'RESET':
return initialState;
default:
return state;
}
}
export const App: FC = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div className='App'>
Count: {state.count}
<button
onClick={() => dispatch({ type: 'INCREMENT', payload: 10 })}
>
Increment 10
</button>
<button
onClick={() => dispatch({ type: 'DECREMENT', payload: 10 })}
>
DECREMENT 10
</button>
<button
onClick={() => dispatch({ type: 'RESET' })}
>
RESET
</button>
</div>
);
};