하나씩 알아가기

[React Hook] useReducer(useState와 비교해보기) 본문

리액트

[React Hook] useReducer(useState와 비교해보기)

clearwater 2021. 1. 31. 16:54
728x90
반응형

오늘은 useReducer hook에 대해서 알아보겠습니다.

 

useReducer는 추가적인 Hook으로 의미가 기본 Hook으로부터 파생되었습니다. useState를 대체할 수 있는 함수인데요. 먼저 useState를 이용하여 counter를 구현해보도록 하겠습니다.

import React, { useState } from 'react';

const Counter = ({ initialCount }) => {
  const [count, setCount] = useState(0);

  return (
    <>
      Count : {count}
      <button onClick={() => setCount(initialCount)}>RESET</button>
      <button onClick={() => setCount((prevState) => prevState - 1)}>-</button>
      <button onClick={() => setCount((prevState) => prevState + 1)}>+</button>
    </>
  );
};

export default Counter;

 

버튼 태그에 setCount 메소드를 onClick 이벤트에 등록해주는데,

setCount의 인자로 함수를 보냅니다.

+ 버튼을 클릭하면 이전상태로부터 1을 증가시키는 함수가 setCount의 인자로 들어가게 됩니다.

 

간단한 경우에는 useState를 쓰는 것이 더 좋다고 생각하지만

현재의 상태에 액션을 받아서 새로운 상태로 갱신하는(reducer) 형태인 경우 useReducer를 사용해야 합니다.

  1. 다수의 하윗값을 포함하는 정적 로직을 만드는 경우
  2. 다음 state가 이전 state에 의존적인 경우

이러한 경우에 useState보다 useReducer가 선호됩니다.

 

useReducer는 첫 번째 인자로 reducer 함수를 받고, 두 번째 인자로는 initialState 객체를 받습니다.

import React, { useReducer } from 'react';

const initialState = { count: 0 };

const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
};

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

  return (
    <>
      Count : {state.count}
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
    </>
  );
};

export default Counter;

 

useReducer는 state와 dispatch를 반환하기 때문에 dispatch로 액션을 보내는 함수를 onClick 이벤트에 등록해 준 것을 알 수 있습니다. 그러면 RESET 버튼은 어떻게 구현할까요?

import React, { useReducer } from 'react';

const init = (initialCount) => {
  return { count: initialCount };
};

const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return init(action.payload);
    default:
      throw new Error();
  }
};

const Counter = ({ initialCount }) => {
  const [state, dispatch] = useReducer(reducer, initialCount, init);

  return (
    <>
      Count : {state.count}
      <button
        onClick={() => dispatch({ type: 'reset', payload: initialCount })}
      >
        RESET
      </button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
    </>
  );
};

export default Counter;

init 함수를 만들어 useReducer의 세 번째 인자로 전달해 주면 됩니다.

 

잘 동작합니다!

728x90
반응형