여러개의 state 와 또 그 state 의 하위 값을 가지는 복잡한 state 를 관리해야 할 때 useReducer 를 사용하면 좀 더 효과적으로 state 를 관리 할 수 있고 코드를 깔끔하게 작성 할 수 있습니다.
useReducer 을 사용하기에 앞서 Reducer, Dispatch, Action 에 대해서 알아야 합니다.
Action 은 Reducer 에게 전달할 state 의 업데이트 내용을 담고 있습니다.
Dispatch 는 Action 을 Reducer 에게 전달해주는 역할을 합니다.
Reducer 는 Action 의 내용을 가지고 state 를 업데이트 해주는 역할을 합니다.
Dispatch 에 인자로 Action 을 담아 Reducer 에게 전달하면 Reducer 는 Action 에 담긴 내용대로 컴포넌트의 state 업데이트를 진행하는 것 입니다.
useReducer 의 사용 방법
const initialstate = {
clickNumber: 0,
};
const reducer = (state, action) => {
switch (action.type) {
case 'CLICK_BUTTON':
return {
clickNumber: state.clickNumber + 1,
};
}
};
const Counter = () => {
const [count, dispatch] = useReducer(reducer, initialstate);
const onclickButton = () => {
dispatch({
type: 'CLICK_BUTTON',
});
};
return (
<>
<div className="screen">
<p>클릭 횟수 : {count.clickNumber}</p>
<button onClick={onclickButton}>클릭</button>
</div>
</>
);
};
위의 코드로 버튼을 클릭한 횟수를 세는 아주 간단한 프로그램을 만들었습니다. 이 프로그램을 만들때 useReducer 을 사용 했습니다.
하나씩 알아보자면
const [count, dispatch] = useReducer(reducer, initialstate);
useReducer 을 사용할때 첫번째 인자는 reducer 함수, 두번째 인자는 초기 state 를 인자로 넘겨 줍니다.
그리고 반환값을 두가지로 구조분해 해 줍니다.
첫번째는 count 라는 현재 state 입니다. 그리고 두번째로는 dispatch 라는 어떤 state 업데이트 내용을 담아 전달할 함수 입니다.
const reducer = (state, action) => {
switch (action.type) {
case 'CLICK_BUTTON':
return {
clickNumber: state.clickNumber + 1,
};
}
};
dispatch 로 전달된 action 의 type 에 따라서 어떻게 state 를 업데이트 할지 코드를 작성 합니다.
reducer 함수의 첫번째 인자로는 현재 state, 두번째 인자로는 dispatch 에 의해서 전달받은 action 객체 입니다.
보통 reducer 함수 내부에서 switch 문을 사용해 action 객체의 type 에 따라서 state 를 업데이트 해 줍니다. 위와 같이 switch 로 state 를 처리할 때 switch 의 case 에 없는 type 이 action 에 의해서 전달 되었다면 state 가 업데이트도 되지 않기 때문에 예상하지 못한 state 의 업데이트를 예방 할 수 있습니다.
case 에 해당 된다면 새로운 객체에 새로운 state 를 담아 return 합니다.
이때 state 의 값이 객체, 배열 형태라면 새로운 객체, 배열을 만들어 반환해야 합니다.
const initialstate = {
clickNumber: 0,
};
초기 스테이트를 객체 형태로 정의 합니다. 사실 이 프로그램에서는 초기 스테이트를 이렇게 따로 객체 형태로 정의 할 필요가 없습니다. 하나의 state 를 관리하기 때문입니다.
const [count, dispatch] = useReducer(reducer, 0);
useReducer 의 두번째 인자에 초기 스테이트로 0 을 전달해도 됩니다.
const onclickButton = () => {
dispatch({
type: 'CLICK_BUTTON',
});
};
위 코드에서는 버튼을 클릭하면 이벤트가 발생해 콜백함수를 호출하고 콜백함수 내부에 dispatch 로 state 업데이트 내용을 action 객체에 담아 reducer 함수에 전달 합니다.
action 객체 안에는 reducer 함수에서 어떤 case 인지 알아야 하기 때문에 type 을 적어 전달 합니다. type 의 내용은 보통 대문자로 작성 합니다.