[React] useReducer

youngseo·2022년 7월 31일
0

REACT

목록 보기
30/52
post-thumbnail

useReducer

리액트에서 자체적으로 제공하는 훅중에 하나입니다. 사실 전역 상태 관리보다는 상태관리에 조금 더 관련이 있습니다.

하지만 이 useReducer는 context API와 리덕스와 함께 사용을 하는 경우가 많기 때문에 개념을 잘 다져놓는 것이 좋습니다.

const [state, dispatch] = useReducer(reducer, initialArg, init);
  • useReducer는 useState의 대체함수입니다.
  • useState의 경우 state와 setState를 반환했다면, useReducer는 statedispatch를 반환합니다.
  • 세번째 인자의 경우 어떤 함수가 들어가는데 많이 사용되지는 않기 때문에 첫번째 인자와 두번쨰 인자에 조금 더 집중해 살펴보면 좋습니다.
    • reducer : (state, action) => newState의 형태로 받습니다.

예시

const initialState = {count: 0};

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

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}
  • 비즈니스 로직과 렌더링 하는 로직이 분리되어 있는 것을 확인할 수 있습니다.

언제 useState를 쓰고 언제 useReducer를 사용하나요?

프로젝트의 크기가 커지다보면 setState를 하기 전에 현재의 state를 조작하는 길이가 길어질 수 있습니다. 이렇게 복잡한 state를 다룰 때 userReducer를 이용해 컴포넌트의 상태와 컴포넌트의 상태를 변화하는 로직을 나눠 다룰 수 있습니다.

또한 state가 이전 state에 의존적인 경우에는 useState보다 useReducer를 선호합니다.

useState의 setState의 경우 비동기로 처리가 되기 때문에 같은 state를 여러번 호출했을 때 state가 병합되어 업데이트가 될 수도 있습니다. 이런 이슈가 useReducer에서는 발생하지 않기 때문에 useState보다 useReducer를 선호합니다.

리액트 공식문서에서 보다 자세한 내용 및 예시를 확인할 수 있습니다.

사용 예시

다음은 지난 번 useContext를 공부하며 만든 예시입니다.

import React, { createContext, useState } from "react";

export const UserContext = createContext();

export default function UserStore(props) {
  const [job, setJob] = useState("FE-developer");

  const user = {
    name: "0seo",
    job,
    changejob: (upatedJob) => setJob(upatedJob),
  };
  return (
    <UserContext.Provider value={user}>{props.children}</UserContext.Provider>
  );
}

현재 예시의 경우 user에 다루는 정보가 많지 않기 떄문에 const [job, setJob] = useState("FE-developer");, const [name, setName] = useState("0seo");과 같이 각각의 상태값을 만들어 사용을 할 수 있지만 프로젝트의 규모가 커지다보면 한계가 있게 됩니다.

이런 경우 useState가 아닌 useReducer를 이용해 관리를 할 수 있습니다.

import React, { createContext, useState, useReducer } from "react";

export const UserContext = createContext();

const initialUser = {
  name: "0seo",
  jog: "FE-developer",
};

const userReducer = (state, action) => {
  switch (action.type) {
    case "changeJob":
      return { ...state, job: action.text };
      break;
    default:
      break;
  }
};

export default function UserStore(props) {
  const [user, dispatch] = useReducer(userReducer, initialUser);

  return (
    <UserContext.Provider value={dispatch}>
      {props.children}
    </UserContext.Provider>
  );
}

BlogPage.js

import React, { useContext } from "react";
import { UserContext } from "../store/user";

export default function BlogPage() {
  const dispatch = useContext(UserContext);
  console.log(dispatch);
  return (
    <div>
      <h1>BlogPage</h1>
      <button
        onClick={() => dispatch({ type: "changeJob", text: "BE-developer" })}
      >
        Change Job
      </button>
    </div>
  );
}

버튼을 누르면 user의 job이 바뀐 것을 확인할 수 있습니다.

3. 예제

3-1 useState를 이용한 로그인 관리

3-2 useReducer를 이용한 로그인 관리

0개의 댓글