useReducer는 useState와 유사하다. 복잡한 논리에 의존하는 여러 상태를 추적하는 경우 useReducer를 사용 할 수 있다.
useReducer([reducer], [initialState]);
reducer 함수는 사용자 정의 상태 논리를 initialState를 포함하며 단순한 값일 수 있지만 일반적으로 개체를 포함한다. useReducer는 state와 dispatch 메서드를 반환한다.
import { useReducer } from "react";
import ReactDOM from "react-dom/client";
const initialTodos = [
{
id: 1,
title: "Todo 1",
complete: false,
},
{
id: 2,
title: "Todo 2",
complete: false,
},
];
const reducer = (state, action) => {
switch (action.type) {
case "COMPLETE":
return state.map((todo) => {
if (todo.id === action.id) {
return { ...todo, complete: !todo.complete };
} else {
return todo;
}
});
default:
return state;
}
};
function Todos() {
const [todos, dispatch] = useReducer(reducer, initialTodos);
const handleComplete = (todo) => {
dispatch({ type: "COMPLETE", id: todo.id });
};
return (
<>
{todos.map((todo) => (
<div key={todo.id}>
<label>
<input
type="checkbox"
checked={todo.complete}
onChange={() => handleComplete(todo)}
/>
{todo.title}
</label>
</div>
))}
</>
);
}
useReducer() hook 함수는 첫번째 인자로 넘어오는 reducer 함수를 통해 컴포넌트의 상태(state)가 행동(action)에 따라 어떻게 변해야하는지를 정의한다. 위에서 작성한 카운터 컴포넌트에서 사용할 reducer 함수는 switch 분기문을 이용하면 이해하기 쉽게 작성 할 수 있다.
const initialTodos = [
{
id: 1,
title: "Todo 1",
complete: false,
},
{
id: 2,
title: "Todo 2",
complete: false,
},
];
const reducer = (state, action) => {
switch (action.type) {
case "COMPLETE":
return state.map((todo) => {
if (todo.id === action.id) {
return { ...todo, complete: !todo.complete };
} else {
return todo;
}
});
default:
return state;
}
};