useState와 같이 상태를 관리하는 또 다른 방법이다. useReducer를 사용하면 컴포넌트의 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있다. 상태 업데이트 로직을 컴포넌트 바깥에 작성 할 수도 있고, 심지어 다른 파일에 작성 후 불러와서 사용할 수도 있다.

reducer

현재 상태와 액션 개체를 파라미터로 받아와서 새로운 상태를 반환해 주는 함수. 여기서 반환하는 상태는 곧 컴포넌트가 지닐 새로운 상태이다.

function reducer(state, action) {
  // 새로운 상태를 만드는 로직
  // const nextState = ...
  return nextState;
}

action

업데이트를 위한 정보를 가지고 있다. action 객체의 형태는 자유이다.

dispatch({액션에 대한 정보}) 이런 형태로 사용한다.

// 카운터에 1을 더하는 액션
{
  type: 'INCREMENT'
}
// 카운터에 1을 빼는 액션
{
  type: 'DECREMENT'
}
// input 값을 바꾸는 액션
{
  type: 'CHANGE_INPUT',
  key: 'email',
  value: '[email protected]'
}

useReducer

형태는 다음과 같다.

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

state가 바로 컴포넌트에서 사용하는 상태이고, dispatch는 액션을 발생시키는 함수이다.

useReducer의 첫번째 파라미터에는 reducer 함수를, 두번째 파라미터는 초기 상태를 넣는다.

reducer 함수를 통해서 state의 값이 action에 따라 어떻게 변화하는지를 리턴하고, 그 리턴 값이 바로 새 state의 값이 된다.

useState 예제 바꿔보기

Counter.js

useState 사용 시

import React, { useState } from 'react';

function Counter() {
  const [number, setNumber] = useState(0);

  const onIncrease = () => {
    setNumber(prevNumber => prevNumber + 1);
  };

  const onDecrease = () => {
    setNumber(prevNumber => prevNumber - 1);
  };

  return (
    <div>
      <h1>{number}</h1>
      <button onClick={onIncrease}>+1</button>
      <button onClick={onDecrease}>-1</button>
    </div>
  );
}

export default Counter;