[React] Hooks - useReducer

Noeyso·2022년 6월 13일
0

React

목록 보기
12/18
post-thumbnail
post-custom-banner

useReducer

  • useState처럼 상태를 관리하고 업데이트할 수 있는 함수이다.
  • 컴포넌트의 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있다.
    => reducer의 장점
  • 현재 상태, 업데이트에 필요한 정보를 담은 액션 값을 전달받아 새로운 상태를 반환하는 함수이다.

(리덕스를 배울때 reducer 개념이 나오게된다.)

Counter 예제를 작성하며 reducer를 사용해보자.


카운터 구현하기

리듀서를 사용해서 카운터를 구현해보자.

import React, { useReducer } from "react";

function reducer(state, action) {
  switch (action.type) {
    case "INCREMENT":
      return { value: state.value + 1 };
    case "DECREMENT":
      return { value: state.value - 1 };
    default:
      return state;
  }
}

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, { value: 0 });

  return (
    <div>
      <p>
        현재 카운터 값은 <b>{state.value}</b>입니다.
      </p>
      <button onClick={() => dispatch({ type: "INCREMENT" })}>+1</button>
      <button onClick={() => dispatch({ type: "DECREMENT" })}>-1</button>
    </div>
  );
};
export default Counter;

코드를 뜯어보자.!

const [state, dispatch] = useReducer(reducer, { value: 0 });

useReducer를 사용한 모양새가 useState랑 꽤나 비슷하다!

useReducer를 사용하기 위해서는 첫 번째 파라미터에는 리듀서 함수를 넣어주고(우리가 만든 reducer 함수를 넘겨주었다.),
두 번째 파라미터에는 해당 리듀서의 기본 값을 넣어주면 된다.

이 함수를 호출하면 state와 dispatch 함수를 반환한다.
여기서 state는 현재의 상태값이고, dispatch는 액션을 발생시키는 함수이다.


<button onClick={() => dispatch({ type: "INCREMENT" })}>+1</button>
<button onClick={() => dispatch({ type: "DECREMENT" })}>-1</button>

이런식으로 dispatch함수의 인자에 액션 값을 넘겨주면 리듀서 함수가 호출된다.

실행해보면 카운터가 잘 구현된 것을 볼 수 있을 것이다.

useState vs useReducer

Counter 함수를 useState와 useReducer를 사용해서 구현했을 때의 차이점을 살펴보자.

  • useState 사용
    useState를 사용할 경우 컴포넌트 안에서 상태 관련 로직들을 정의하고 사용한다.
  • useReducer 사용
    useReducer를 사용할 경우 상태 관련 로직들을 컴포넌트와 분리해서 사용할 수 있다.



인풋 상태 관리하기

이번에는 useReducer를 사용해서 Input 상태를 관리해보자.

import React, { useReducer } from "react";

function reducer(state, action) {
  return {
    ...state,
    [action.name]: action.value,
  };
}

const Info = () => {
  const [state, dispatch] = useReducer(reducer, { name: "", nickname: "" });
  const { name, nickname } = state;
  const onChange = (e) => {
    dispatch(e.target);
  };

  return (
    <div>
      <div>
        <input name="name" value={name} onChange={onChange} />
        <input name="nickname" value={nickname} onChange={onChange} />
      </div>
      <div>
        <b>이름 : </b> {name}
      </div>
      <div>
        <b>닉네임 : </b>
        {nickname}
      </div>
    </div>
  );
};

export default Info;

useReducer의 액션은 어떤 값도 사용이 가능하다.
그래서 이 예제에서는 이벤트 객체가 갖고있는 e.target 값 자체를 액션 값으로 사용했다.

코드를 뜯어보자.

const [state, dispatch] = useReducer(reducer, { name: "", nickname: "" });
  • useReducer 함수에 우리가 만든 reducer 함수와 state 기본 값을 인자로 넘겨주었다.
  • 그러면 useReducer는 현재 상태(state)와 액션을 발생시키는 함수(dispatch)를 반환한다.

const onChange = (e) => {
    dispatch(e.target);
  };
  • input 값이 변화 할 때마다 onChange 함수가 호출된다.
  • 즉, input 값이 변화 할 때마다 dispatch 함수가 호출되고 해당 input의 이벤트 객체 값(e.target)이 액션 값으로 넘어간다.

function reducer(state, action) {
  return {
    ...state,
    [action.name]: action.value,
  };
}

reducer 함수는 state를 반환하고 있다.
(기존의 state에서 변경된 부분은 값을 바꿔서 반환해주고 있다.)

  • [action.name] : 우리가 input 코드에 설정해준 name 속성을 가져온다.
  • action.value : input에 입력된 값을 가져온다.


마치며

Redux를 잠깐 공부했을때 리듀서의 개념을 배운 적이 있다. 굉장히 어렵다고 느꼈었는데 오늘 이렇게 useReducer를 직접 사용해보고 개념을 정리하는 과정에서 Reducer의 개념과 로직을 잘 이해할 수 있게 됐다.
특히, useState와 useReducer를 둘 다 사용해서 같은 예제를 작성하고 비교해보니 그 차이가 확실히 느껴졌고 두 Hooks의 개념이 더 와닿았다.

profile
React,Typescript를 공부하고 있는 주니어 프론트엔드 개발자입니다. 👩🏻‍💻
post-custom-banner

0개의 댓글