[Hook] - useReducer

Donggu(oo)·2023년 6월 16일
0

React

목록 보기
18/30
post-thumbnail

1. useReducer의 개념


  • useReducer 훅이 사용하는 리듀서 함수는 아래와 같은 형태를 가진다. 순수 함수여야 하기 때문에 state와 action을 변경해서는 안 되고, 반드시 새로운 상태를 만들어서 리턴해야 한다.
(state, action) => {
  //state와 action을 이용해 연산을 수행한 후 새로운 상태(newState)를 리턴한다.
  return newState;
};
  • 상태를 변경할 때는 리듀서 함수의 첫 번째 인자로 기존 상태가 전달된다. 기존 상태는 불변성을 가져야 하므로 그대록 두고, 새로운 상태를 만들어서 리턴하면 이것이 새로운 상태가 된다.

  • 리액트는 상태가 바뀌면 UI도 갱신되므로 상태의 변경 추적이 디버깅 시 필요한데, 리듀서를 사용하면 과거 시점의 상태가 그대로 유지되므로 언제든지 과거 시점의 상태 데이터를 확인할 수 있고 시간대별로 상태가 어떻게 변경됐는지를 추적할 수 있다.

  • 단순히 상태를 관리하고 변경하는 거라면 useState 훅을 사용해도 충분하지만 useReducer 훅을 사용하면 아래와 같은 장점이 있다.

    1. 상태 관리 기능을 컴포넌트로부터 분리할 수 있고, 유사한 상태 관리 기능을 사용하는 여러 컴포넌트가 상태 변경과 관리 기능을 공유할 수 있다.
    2. 불변성을 가지는 상태 변경을 강제하게 되므로 상태 변경을 추적하기가 용이하다.

2. useReducer 훅 사용하기


import { useReducer } from 'react'
  • useReducer 훅에 리듀서 함수와 초기 상태를 인자로 전달하여 호출하면 상태와 상태 변경을 위해 메시지를 전달할 수 있는 dispatch 함수가 리턴된다.

  • dispatch 함수가 미리 정의한 형식의 메시지를 전달하면 상태를 변경하도록 리듀서 함수를 작성해야 한다.

기본 구문

const [state, dispatch] = useReducer(reducer, initialState);

매개 변수

  • state : 상태
  • dispatch : 상태를 변경하는 메서드
  • reducer : 새로운 상태를 리턴하는 리듀서 함수
  • initialState : 초기 상태로 지정할 객체
  • 아래의 예제는 input change에 따른 이벤트와 Increment age 버튼 클릭 시 초기값인 42에서 1씩 증가하는 action을 전달한다.
// infoReducer.js
const initialState = { name: "Taylor", age: 42 };

const infoReducer = (state, action) => {
  switch (action.type) {
    case "changed_name":
      return {
        name: action.nextName,
        age: state.age,
      };
    case "incremented_age":
      return {
        name: state.name,
        age: state.age + 1,
      };
    default:
      return state;
  }
};

export { initialState, infoReducer };
// Form.js
import { useReducer } from "react";
import { initialState, infoReducer } from "./infoReducer";

function Form() {
  const [state, dispatch] = useReducer(infoReducer, initialState);

  const handleInputChange = (e) => {
    dispatch({
      type: "changed_name",
      nextName: e.target.value,
    });
  };

  const handleButtonClick = () => {
    dispatch({ type: "incremented_age" });
  };

  return (
    <>
      <input value={state.name} onChange={handleInputChange} />
      <button onClick={handleButtonClick}>Increment age</button>
      <p>
        Hello, {state.name}. You are {state.age}.
      </p>
    </>
  );
}

export default Form;

0개의 댓글