what is useReducer?
reducer는 state 관리를 돕는 훅으로, useState와 비슷하다. 대신 useState보다 더 많은 기능을 가지고 있기 때문에, 복잡한 state를 관리할 때에는 state 대신 reducer를 사용한다. 복잡한 state란 어떤 state일까?
- 어떤 state의 업데이트가 다른 state에 의존하고 있다(그래서 최신 state를 보장받을 수 없을 때).
- 서로 연관있는 state가 여러 개 존재하고 있다(action 객체 데이터나, state를 객체로 관리해서 하나의 state로 관리 가능).
How to use Reducer?
const [state, dispatchFn] = useReducer(reducerFn, initialState, initFn)
- state | 가장 최신의 state, useState의 state와 같음
- dispatchFn | 새로운 action을 dispatch(=send) 하는 함수
- dispatch(action)
- action은 보통 객체 데이터로, 어떤 데이터를 보낼 것인지 코드로 설정할 수 있다.
- reducerFn | dispatchFn이 action을 보내면(dispatch가 실행되면) 호출되는 함수
- (prevState, action) => { return newState }
- 업데이트 된 state를 반환해야 한다.
- useState이 콜백함수를 전달받을 때의 확장된 버전이라고 볼 수 있다(prev => { }).
어떤 state가 다른 state에 의존하고 있을 때
const Login = (props) => {
const emailChangeHandler = (event) => {
setEnteredEmail(event.target.value);
setFormIsValid(
event.target.value.includes('@') && enteredPassword.trim().length > 6
)
};
const passwordChangeHandler = (event) => {
setEnteredPassword(event.target.value);
setFormIsValid(
event.target.value.trim().length > 6 && enteredEmail.includes('@')
)
};
}
- 두 changeHandler 함수는 form 유효성 상태를 업데이트 하고 있다.
- form 유효성 상태는 다른 state(entered input)를 기반으로 업데이트 된다.
- 이 때 entered input의 state가 가장 최신의 state임을 보장할 수 없다.
- 어떤 state를 업데이트 할 때, set의 콜백 함수 인자로 그 state의 prevState를 전달할 수 있다.
- 예를 들어 댓글 리스트를 업데이트 한다고 하자. 이전의 모든 댓글 리스트(prevState)를 받아와서, 그 리스트에 새로운 아이템을 더하는 형식으로 업데이트할 것이다.
- 그러나 form 유효성 업데이트 함수는 자기 자신의 prevState가 아니라, 다른 state(enterd input)에 의존하고 있다.
- 콜백의 인자로는 자기 자신의 prevState 만을 전달할 수 있으므로, entered input의 prevState는 인자로 전달할 수 없다. 즉 entered input의 가장 최신 state를 보장받을 수 없다.
연관있는 여러 state가 존재할 때
useState
const [emailInput, setEmailInput] = useState({ value: '', isValid: null });
const emailChangeHandler = (event) => {
setEmailInput({
value: event.target.value,
isValid: event.target.value.includes('@'),
});
};
const validateEmailHandler = () => {
setEmailInput((prev) => { ...prev });
};
useReducer
const [pwInput, dispatchPwInput] = useReducer(
// reducer
(prev, action) => {
if (action.type === 'USER_INPUT') {
return { ...prev, value: action.value, isValid: action.value.includes('@') };
}
if (action.type === 'INPUT_BLUR') {
return { ...prev, isFocused: true };
}
if (action.type === 'RESET') {
return { value: '', isValid: null };
}
},
// initial state
{ value: '', isValid: null }
);
const passwordChangeHandler = (event) => {
dispatchPwInput({ // action
type: 'USER_INPUT',
value: event.target.value,
});
};
const passwordBlurHandler = () => {
dispatchPwInput({ type: 'INPUT_BLUR' });
};
'Study > React' 카테고리의 다른 글
Rules of Hooks (0) | 2022.06.20 |
---|---|
useContext (0) | 2022.06.20 |
useEffect (0) | 2022.06.19 |
useRef (0) | 2022.06.18 |
Fragment & Portal (0) | 2022.06.18 |