개요
useReducer
는 컴포넌트에 reducer(상태 업데이트 함수)를 추가할 수 있게 해주는 React Hook입니다. 복잡한 상태 로직이나 여러 값이 얽힌 상태를 관리할 때 유용합니다.
const [state, dispatch] = useReducer(reducer, initialArg, init?)
Reference
useReducer(reducer, initialArg, init?)
컴포넌트의 최상위에서 useReducer
를 호출하면, reducer를 통해 상태를 관리할 수 있습니다.
import { useReducer } from 'react';
function reducer(state, action) {
// ...
}
function MyComponent() {
const [state, dispatch] = useReducer(reducer, { age: 42 });
// ...
}
파라미터
reducer
: 상태를 어떻게 업데이트할지 명시하는 순수 함수. (state, action)을 받아 다음 state를 반환합니다.initialArg
: 초기 state를 계산할 값. 어떤 타입이든 가능하며, init이 없으면 이 값이 초기 state가 됩니다.init
(선택): 초기 state를 반환하는 함수. 있으면init(initialArg)
의 결과가 초기 state가 됩니다.
반환값
[state, dispatch]
: 현재 state와, state를 업데이트하는 dispatch 함수가 배열로 반환됩니다.
dispatch 함수
dispatch 함수는 state를 업데이트하고 리렌더를 트리거합니다. action을 인자로 받아 reducer에 전달합니다.
const [state, dispatch] = useReducer(reducer, { age: 42 });
function handleClick() {
dispatch({ type: 'incremented_age' });
}
- action은 보통 type 속성을 가진 객체입니다.
- dispatch는 반환값이 없습니다.
- dispatch 후 바로 state를 읽으면 이전 값이 반환됩니다(업데이트는 다음 렌더에 반영).
사용법
컴포넌트에 reducer 추가하기
import { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'incremented_age':
return { ...state, age: state.age + 1 };
default:
throw Error('Unknown action: ' + action.type);
}
}
function MyComponent() {
const [state, dispatch] = useReducer(reducer, { age: 42 });
return (
<>
<div>나이: {state.age}</div>
<button onClick={() => dispatch({ type: 'incremented_age' })}>나이 증가</button>
</>
);
}
복잡한 초기화 로직이 필요한 경우
function createInitialState(username) {
return {
draft: '',
todos: [],
user: username
};
}
const [state, dispatch] = useReducer(reducer, username, createInitialState);
트러블슈팅
dispatch 후 state가 바로 바뀌지 않는 경우
- dispatch는 다음 렌더에만 state를 반영합니다. 즉시 state를 읽으면 이전 값이 반환됩니다.
- 필요하다면 reducer를 직접 호출해 다음 state를 예측할 수 있습니다.
state가 undefined가 되는 경우
- reducer에서 모든 case에 대해 state를 반환해야 하며, 알 수 없는 action에는 에러를 throw하세요.
객체/배열 직접 변경 시 화면이 갱신되지 않는 경우
- state를 직접 변경하지 말고, 항상 새 객체/배열을 반환하세요.
"Too many re-renders" 오류
- 렌더링 중에 dispatch를 호출하면 무한 루프가 발생합니다. 반드시 이벤트 핸들러 등에서만 dispatch를 호출하세요.
Strict Mode에서 reducer/initializer가 두 번 실행되는 경우
- 개발 환경에서만 순수성 검증을 위해 두 번 실행됩니다. 한 번의 결과만 사용되므로, 순수 함수라면 문제 없습니다.
반응형