Reducer

Doozuu·2023년 2월 18일
0

React

목록 보기
11/23
post-custom-banner

📌 Context & Reducer & Redux

Context

React Context API는 React에 내장된 상태 관리 솔루션이다.

Redux

Redux는 외부 라이브러리로, Context API와 유사한 역할을 하는 상태 관리 솔루션이다.

Redux를 이해하기 위해 먼저 Reducer가 뭔지 알아보아야 한다.

Reducer

Reducer는 상태 관리를 위한 패턴이다.

단순한 경우에는 Reducer를 Context와 함께 쓰는 것보다 Context만 사용하는게 더 간단하지만, 관리해야 할 데이터가 복잡한 경우 Reducer를 사용하는게 더 좋다.
(Reducer 사용방식이 복잡해서 처음에 이해하기 좀 어렵다..)



기존의 Context & useState 방식

ex.
장바구니의 아이템과 개별 수량, 전체 수량 정보를 관리하는 Cart Context가 있을 때, 각각의 상태는 각각의 useState를 통해 관리된다.

Context & Reducer 방식

context 방식과 매우 유사한 방식으로 상태를 관리하지만, 보다 직관적이고 useState를 사용하지 않는다는 차이점이 있다.

Reducer는 Action을 활용해 어떤 동작을 수행할지 지시한다.

Action은 객체이며 두가지 key로 구성되어 있는데, typepayload이다.

  • type은 어떤 동작을 수행할지 문자열로 나타내는 부분이다.
  • payload는 전달할 값을 담는 부분으로 어떤 형태든(배열, 객체) 나타낼 수 있다.



두 가지 방식을 코드로 비교해보기

  1. 기존의 Context & useState 방식
import { createContext, useEffect, useReducer } from "react";

import {
  onAuthStateChangedListener,
  createUserDocumentFromAuth,
} from "../firebase/firebase.utills";

export const UserContext = createContext({
  setCurrentUser: () => null,
  currentUser: null,
});

export const UserProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(null);
  const value = { currentUser, setCurrentUser };

  useEffect(() => {
    const unsubscribe = onAuthStateChangedListener((user) => {
      if (user) {
        createUserDocumentFromAuth(user);
      }
      setCurrentUser(user);
    });

    return unsubscribe;
  }, []);

  return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};
  1. Context & Reducer 방식
  1. useReducer import 하기
  2. INITIAL_STATE 세팅하기
  3. USER_ACTION_TYPES 담아두기
    (오타 방지를 위해 객체에 따로 담아서 보관)
  4. Reducer 함수 만들기
    switch를 이용해 케이스별로 어떤 동작을 시행할지 지정한다.
    default 동작은 error throw하기.
  5. useReducer로 Reducer 함수와 INITIAL_STATE 가져오기.
    dispatch로 action 일으키기
import { createContext, useState, useEffect, useReducer } from "react";

import {
  onAuthStateChangedListener,
  createUserDocumentFromAuth,
} from "../firebase/firebase.utills";

export const UserContext = createContext({
  setCurrentUser: () => null,
  currentUser: null,
});

export const USER_ACTION_TYPES = {
  SET_CURRENT_USER: "SET_CURRENT_USER ",
};

const INITIAL_STATE = {
  currentUser: null,
};

const userReducer = (state, action) => {
  const { type, payload } = action;

  switch (type) {
    case USER_ACTION_TYPES.SET_CURRENT_USER:
      return { ...state, currentUser: payload };
    default:
      throw new Error(`Unhandled type ${type} in userReducer`);
  }
};

export const UserProvider = ({ children }) => {
  const [{ currentUser }, dispatch] = useReducer(userReducer, INITIAL_STATE);

  const SetCurrentUser = (user) =>
    dispatch({ type: USER_ACTION_TYPES.SET_CURRENT_USER, currentUser: user });

  useEffect(() => {
    const unsubscribe = onAuthStateChangedListener((user) => {
      if (user) {
        createUserDocumentFromAuth(user);
      }
      SetCurrentUser(user);
    });

    return unsubscribe;
  }, []);

  const value = { currentUser };

  return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};
profile
모든게 새롭고 재밌는 프론트엔드 새싹
post-custom-banner

0개의 댓글