useState처럼 state를 생성하고 관리해 주는 도구이다.
여러개의 하위값을 포함하는 복잡한 state를 다뤄야 할때, useState 대신 useReducer를 사용하면 더 깔끔하게 코드를 짤 수 있고, 유지보수도 한결 편해진다.
useReducer를 알기전에, Reducer Dispatch Action 이 세가지 먼저 알아야 한다.
간단하게 준영이라는 사람이 있고 은행에서 돈을 빼야하는 상황이라고 가정한다면, 준영이라는 사람이 은행에게 요구(DIspatch)를 하면, 그 요구에는 내용(Action)이 있고, 은행이라는 Reducer(state를 업데이트 해주는 역할)에서 돈이라는 state를 Action에 맞게 정하여 주는 것이다. 이것을 컴포넌트의 관점으로 본다면, 아래 그림과 같이 나타낼 수 있다.
예시로 잔고가 있고, 얼마를 예금 또는 출금을 할지 입력하는 간단한 앱을 만들었다.
아직 완성된 코드는 아니지만, useReducer를 사용해 완성해 보자
import { useState } from "react";
// useReducer는 세가지로 나뉜다
// reducer - state를 업데이트 하는 역할 (은행)
// dispatch - state 업데이트를 위한 요구
// action - 요구의 내용
export default function UseReducerPage() {
const [number, setNumber] = useState(0);
return (
<div>
<div>useReducerPractice!</div>
<hr />
<p>잔고: ?원</p>
<input
type={"number"}
value={number}
onChange={(event) => setNumber(Number(event.target.value))}
step={"1000"}
/>
<button>예금</button>
<button>출금</button>
</div>
);
}
useReducer
의 사용 방법은 다음과 같다.
const reducer = (state, action) => {}
const [money, dispatch] = useReducer(reducer, 0);
import { useReducer, useState } from "react";
// useReducer는 세가지로 나뉜다
// reducer - state를 업데이트 하는 역할 (은행)
// dispatch - state 업데이트를 위한 요구
// action - 요구의 내용
const reducer = (state, action) => {
console.log(
"dispatch하여 reducer함수가 불려져 일을 시작, 요구 내용: " + action.type,
action.payload + ", state: " + state
);
return state + Number(action.payload);
};
export default function UseReducerPage() {
const [number, setNumber] = useState(0);
const [money, dispatch] = useReducer(reducer, 0);
return (
<div>
<div>useReducerPractice!</div>
<hr />
<p>잔고: {money}원</p>
<input
type={"number"}
value={number}
onChange={(event) => setNumber(Number(event.target.value))}
step={"1000"}
/>
<button
onClick={() => {
dispatch({ type: "예금", payload: number });
}}
>
예금
</button>
<button>출금</button>
</div>
);
}
🙋🏻♂️ 예금 버튼의 onClick으로 dispatch()
를 호출하면, reducer()
가 호출 된다. reducer는 인자로 state와 action을 가지고, action은 dispatch의 { type: "예금", payload: number }
정보를 가지게 된다.
import { useReducer, useState } from "react";
// useReducer는 세가지로 나뉜다
// reducer - state를 업데이트 하는 역할 (은행)
// dispatch - state 업데이트를 위한 요구
// action - 요구의 내용
const reducer = (state, action) => {
console.log(
"dispatch하여 reducer함수가 불려져 일을 시작, 요구 내용: " + action.type,
action.payload + ", state: " + state
);
switch (action.type) {
// dispatch의 type이 예금 일 때..
case "예금":
return state + Number(action.payload);
// dispatch의 type이 출금 일 때..
case "출금":
return state - Number(action.payload);
// dispatch의 type이 아무것도 아닐 때, 기본 값..
default:
return state;
}
};
export default function UseReducerPage() {
const [number, setNumber] = useState(0);
const [money, dispatch] = useReducer(reducer, 0);
return (
<div>
<div>useReducerPractice!</div>
<hr />
<p>잔고: {money}원</p>
<input
type={"number"}
value={number}
onChange={(event) => setNumber(Number(event.target.value))}
step={"1000"}
/>
<button
onClick={() => {
dispatch({ type: "예금", payload: number });
}}
>
예금
</button>
<button
onClick={() => {
dispatch({ type: "출금", payload: number });
}}
>
출금
</button>
</div>
);
}