useReducer
1
const [state, dispatch] = useReducer(reducer, initialArg, init);
리액트 공식문서에 의하면 useState의 대체 함수라고 설명한다. reducer는 (state, action) => newState 형태의 함수이다. 그리고 reducer는 현재의 State(initialState)와 쌍으로 dispatch 메서드를 반환한다.
개인적으로 리액트를 처음 공부할때부터 참 잘 이해가 가지 않는 부분이 Reducer였다. 이해가 잘 안될때는 코드가 오히려 더 편할 때가 있다. 카운터 예제 코드를 보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const initialState = { count: 0 };
function reducer(state, action) {
switch(action.type) {
case: 'increment' :
return { count: state.count + 1 };
case: 'decrement' :
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [ state, dispatch ] = useReducer(reducer, initialState);
return (
<>
Count: { state.count }
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
reducer함수는 초기의 state값을 받아서, action.type에 따라 state를 새로운 state로 만들어 준다. useReducer는 이 reducer함수(action.type에 따라 어떤 연산을 할 것인지…)와 초기 state 값을 인자로 받아서 state와 dispatch를 쌍으로 반환한다. 여기서 반환된 state는 아직 reducer가 실행되지 않았으니 초기 state 값이 들어있다. dispatch 함수는 action 오브젝트를 인자로 받으며, action.type을 reducer함수에 전달한다.
그러니까 dispatch함수는 reducer 함수를 불러오는 놈이구나…
추가적으로 reducer함수를 만들 때 주의할 점이 있다. 벨로퍼트 선생님의 “리액트를 다루는 기술”에서 참조한다.
- 리듀서 함수는 이전 상태와 객체를 파라미터로 받는다.
- 파라미터 외의 값에는 의존하면 안된다.
- 이전 상태는 절대로 건드리지 않고, 변화를 준 새로운 상태 객체를 만들어서 반환한다.
- 똑같은 파라미터로 호출된 리듀서 함수는 언제나 똑같은 결과 값을 반환해야 한다.
내일은 useRef와 ForwardRef를 정리해야겠다. 얼른 Hooks를 정리하고 Redux를 정리하고 싶다.