useReducer

로선생·2021년 8월 26일

Hooks

목록 보기
3/6

useReducer는 useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트해 주고 싶을 때 사용하는 Hook이다.

(리듀서는 현재 상태, 그리고 업데이트를 위해 필요한 정보를 담은 액션 값을 전달받아 새로운 상태를 반환하는 함수이다. 리듀서 함수에서 새로운 상태를 만들 때에는 반드시 불변성을 지켜야 한다.)

리덕스에서 사용하는 액션 객체에는 어떤 액션인지 알려 주는 type 필드가 꼭 있어야 하지만,
useReducer에서 사용하는 액션 객체는 반드시 type을 지니고 있을 필요가 없다.

카운터 구현하기

// Counter2.js

import React, { useReducer } from "react";

function reducer(state, action) {
  // action.type에 따라 다른 작업 수행
  switch (action.type) {
    case "INCREMENT":
      return { value: state.value + 1 };
    case "DECREMENT":
      return { value: state.value - 1 };
    default:
      // 아무것도 해당되지 않을 때 기존 상태 반환
      return state;
  }
}

const Counter2 = () => {
  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 Counter2;

useReducer의 첫 번째 파라미터에는 리듀서 함수를 넣고, 두 번째 파라미터에서는 해당 리듀서의 기본 값을 넣어 준다.
이 Hook을 사용하면, state값과 dispath함수를 받아 오는데,
여기서 state는 현재 가리키고 있는 상태이고 dispatch는 액션을 발생시키는 함수이다.
dispatch(action)과 같은 형태로 함수 안에 파라미터로 액션 값을 넣어 주면 리듀서 함수가 호출되는 구조이다.

useReducer를 사용했을 때의 가장 큰 장점은 컴포넌트 업데이트 로직을 컴포넌트 바깥으로 빼낼 수 있다는 것이다.

App.js

import React from 'react';
import Counter from './Counter';
 
const App = () => {
  return <Counter />;
};
 
export default App;

인풋 상태 관리하기

useReducer를 활용하여 Info 컴포넌트에서 인풋 상태를 관리해보자.
인풋이 여러개일 때는 useState를 여러 번 사용했지만,
useReducer를 사용하면 기존 클래스형 컴포넌트에서 setState를 해 준 것과 유사한 방식으로 작업을 처리할 수 있다.

//Info.js

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>
        <div>
          <b>이름:</b> {name}
        </div>
        <div>
          <b>닉네임:</b> {nickname}
        </div>
      </div>
    </div>
  );
};

export default Info;

useReducer에서의 액션은 그 어떤 값도 사용 가능하다.
이벤트 객체가 지니고 있는 e.target값을 액션 값으로 사용하였다.
이와 같이 인풋을 관리하면 인풋의 개수가 아무리 많아져도 코드를 깔끔하게 유지할 수 있다.

// App.js

import React from "react";
import Info from "./Component/Info";

const App = () => {
  return <Info />;
};

export default App;

profile
이제는 이것저것 먹어요

0개의 댓글