조금 더 복잡한 상태 관리를 할 때 사용하는 리액트 훅.
넓은 범위에서는 useState와 비슷하다.
// useState
const [todos, setTodos] = useState([]);
// useReducer
const [todos, dispatch] = useReducer(reducer, []);
useState와 비교하며 보면 더 빠르게 익힐 수 있을 것 같아 위와 같이 사용 예시를 작성하였다.
기본적으로 useReducer는 두 매개변수로 reducer 함수
와 객체의 초기값
을 받는다.
그리고 useState를 사용할 때 객체의 값을 변경하기 위한 함수인 set-
은 useReducer에서 dispatch
로 변경된다.
예시 코드와 함께 useReducer의 특징, 적용 방식을 기록하려고 한다.
위 코드는 지난 useRef 포스트에서 사용한 코드를 포함하고 있다.
먼저 useReducer는 todos 객체에 Line4와 같이 사용하였다. 매개변수로는 reducer 함수와 todos 객체의 초기값인 빈 배열을 넣었다.
함수 onClickAdd와 onClickDelete는 서로 다른 컴포넌트에 해당 함수를 props로 전달하기 위해 만들어졌는데, 이 때 함수 내부에서 dispatch
를 통해 액션 객체를 인수로 전달한다.
reducer 함수와 액션 객체 타입의 선언은 다음과 같이 할 수 있다.
// Action 객체의 타입을 서로소 유니온 타입으로 정의함(!)
type Action =
| {
type: "CREATE";
data: {
id: number;
content: string;
};
}
| {
type: "DELETE";
id: number;
}
// reducer 함수: state와 action 객체를 매개변수로 받음.
function reducer(state: Todo[], action: Action) {
switch (action.type) {
case "CREATE": {
return [...state, action.data];
}
case "DELETE": {
return state.filter((it) => it.id !== action.id)
}
}
}
reducer 함수는 매개변수로 state
와 action
객체를 받는다.
사용하려고 하는 액션 객체의 타입을 Action이라는 이름의 타입으로 선언하고, reducer 함수에서 그 타입에 따른 작업을 구현하였다.
먼저 onClickAdd 함수에서 사용될 "CREATE" 액션의 경우 배열을 반환하는데, 그 배열에는 기존 Todo 배열의 모든 요소를 spread 연산자를 이용해 넣고, dispatch를 통해 받은 액션 객체를 배열의 맨 뒤에 추가한다.
onClickDelete 함수에서 사용될 "DELETE" 액션의 경우 기존 Todo 배열에서 액션 객체가 가진 id 값을 가진 요소를 제거한 배열을 반환한다.
➰ 장점
➰ 단점