본문 바로가기
Coding/REACT

[React] Context API + useReducer 로 전역 상태 관리 하기

by 하상원이야 2022. 8. 23.

useReducer

여러 state를 초기 값으로 가질 수 있고, setState 대신 state를 바꾸는 함수와, state의 초기 값이 들어간다.
import React, { useReducer } from 'react';

const exampleInitialData = {
  number: 0,
  text: '기본 값',
};

const exampleReducer = (state, action) => {
  // eslint-disable-next-line default-case
  switch (action) {
    case 'UP': {
      return { ...state, number: state.number + 1 };
    }
    case 'DOWN': {
      return { ...state, number: state.number - 1 };
    }

    case 'toKOR': {
      return { ...state, text: '기본 값' };
    }
    case 'toENG': {
      return { ...state, text: 'default' };
    }
  }
};

const Main = () => {
  const [state, dispatch] = useReducer(exampleReducer, exampleInitialData);

  return (
    <div>
      <div>
        <h1>{state.text}</h1>
        <button onClick={() => dispatch('toKOR')}>KOR</button>
        <button onClick={() => dispatch('toENG')}>ENG</button>
      </div>
      <h1>{state.number}</h1>
      <button onClick={() => dispatch('DOWN')}>-</button>
      <button onClick={() => dispatch('UP')}>+</button>
    </div>
  );
};

export default Main;

결과 화면

귀여운 리듀서

버튼을 클릭하면 다 잘 작동한다. 이게 useReducer 다. 

 

useContext / createContext

createContext 로 만들고, 만든 context로 감싼 태그 안에서는 useContext를 사용하여 전역 변수를 사용할 수 있다.
import React, { createContext, useContext } from 'react';

const exampleContext = createContext();

const Main = () => {
  const contextName = '전역 변수';
  return (
    <exampleContext.Provider value={contextName}>
      <h1>Parent : {contextName}</h1>
      <Child />
    </exampleContext.Provider>
  );
};

const Child = () => {
  const a = useContext(exampleContext);
  return (
    <div>
      <h3>Child : {a}</h3>
      <ChildinChild />
    </div>
  );
};

const ChildinChild = () => {
  const b = useContext(exampleContext);
  return (
    <div>
      <h5>Child in Child : {b}</h5>
    </div>
  );
};

export default Main;

결과 화면

귀여운 Context

 

여러 컴포넌트에서 Props를 사용하지 않고 변수를 사용하는 모습.

컴포넌트 파일을 분리했다면, 만든 곳에서만 create를 쓰고 나머지에선 useContext를 써서 불러오면 되는 것.

 

 

자. 이제 두 개를 합쳐서 전역 상태 관리를 하자 !

import React, { useReducer, createContext, useContext } from 'react';

const exampleContext = createContext();

const exampleInitialData = {
  number: 0,
  text: '기본 값',
};

const exampleReducer = (state, action) => {
  // eslint-disable-next-line default-case
  switch (action) {
    case 'UP': {
      return { ...state, number: state.number + 1 };
    }
    case 'DOWN': {
      return { ...state, number: state.number - 1 };
    }

    case 'toKOR': {
      return { ...state, text: '기본 값' };
    }
    case 'toENG': {
      return { ...state, text: 'default' };
    }
  }
};

const Main = () => {
  return (
    <exampleContext.Provider
      value={useReducer(exampleReducer, exampleInitialData)}
    >
      <Child />
    </exampleContext.Provider>
  );
};

const Child = () => {
  const [state, dispatch] = useContext(exampleContext);
  return (
    <div>
      <h1>{state.text}</h1>
      <button onClick={() => dispatch('toKOR')}>KOR</button>
      <button onClick={() => dispatch('toENG')}>ENG</button>
      <h1>{state.number}</h1>
      <button onClick={() => dispatch('DOWN')}>-</button>
      <button onClick={() => dispatch('UP')}>+</button>
    </div>
  );
};

export default Main;

createContext, Initial, Reducer는 파일을 밖으로 빼서 따로 관리하는 것이 좋다. 

이유는 유지 보수 용이 일 것 같음. 깔끔하기도 하고. 아님 말고

하여튼 이렇다. 이론 공부는 끝이고 이제 실제로 코드를 쳐보고 공부하겠다. 끝 !

 

위 코드들은 수제로 작성된 신선한 코드입니다.

반응형

댓글