컴포넌트에서 관리하는 state
정보가 너무 많거나 다른 컴포넌트와의 연결로 인한 의존성이 증가될 경우 자연스럽게 redux
와 같은 state 관리의 필요성을 느끼게 됩니다.
하지만 redux나 mobx와 같은 라이브러리를 도입하기에는 또 그다지 크지 않은 규모의 state의 관리라면 useReducer
hook을 통해 간단하게 해결할 수 있습니다.
useState
의 대체 함수로 (state, action) => newState의 형태로 reducer를 받고 dispatch 메서드와 짝의 형태로 현재의 state를 반환하는 hook 입니다.
다수의 하윗값을 포함하는 정적 로직을 만드는 경우나 다음 state가 이전 state에 의존적인 경우에 보통 useState
보다 useReducer
를 선호합니다.
useReducer를 하나의 컴포넌트에서 사용한다면 상관이 없지만, 다수의 컴포넌트에서 사용해야 한다면 custom hooks로 만들어서 사용하는 것이 편리합니다.
// useCounterReducer.js
import React, {useReducer} from "react";
const reducer = (oldState, action) => {
switch(action.type) {
case: "INCREASE:
return oldState + action.number;
case: "DECREASE:
return oldState - action.number;
case: "RESET":
return oldState = 0;
default:
return oldState;
}
}
const useCountReducer = () => {
// useReducer 함수의 첫 번째 인자는 reducer 함수고 두 번째 값은 초기 state값입니다.
const [count, countDispatch] = useReducer(reducer, 0);
return {count, countDispatch}
}
useCountReducer
custom hook을 불러와 사용하도록 하겠습니다.
import React from "react";
import useCountReducer from "./useCountReducer";
const App = () => {
const { count, countDispatch } = useCountReducer();
const onIncrease = () => countDispatch({ type: "INCREASE", number: 1 });
const onDecrease = () => countDispatch({ type: "DECREASE", number: 1 });
const onReset = () => countDispatch({ type: "RESET" });
return (
<div>
<h1>{count}</h1>
<button onClick={onIncrease}>INCREASE</button>
<button onClick={onDecrease}>DECREASE</button>
<button onClick={onReset}>RESET</button>
</div>
);
};
export default App;
이처럼 count라는 정보를 한 군데서 관리할 수 있으면서도, 이 값에대한 접근 및 수정은 커스텀 훅스를 통해 어떤 컴포넌트에서든 가능하다는 것을 알 수 있습니다.
또한 부모-자식 컴포넌트간의 props로 인한 의존성이 사라지면서 props로 인한 리렌더링을 방지할 수도 있습니다.
실제 코드의 동작 예시는 아래에서 확인할 수 있습니다.