[React]Context API

UkiUkhui·2021년 10월 30일

React 공부중

목록 보기
20/25

Context API

  • 전역적으로 사용할 API 있을 경우 유용하게 사용 : 사용자 로그인 정보, 애플리케이션 환경설정, 테마 등
  • 예 : 리덕스, 리액트 라우터, styled-component
  • 상태 뿐 아니라 함수, DOM도 전역적으로 관리할 수 있음
  • react component 안에서 global한 데이터 공유
  • 같은 데이터를 트리 안 여러 레벨이 있는 많은 컴포넌트에게 주어야 할 때 사용

    데이터 값이 변할 때마다 모든 하위 컴포넌트에게 "broadcast"하는 역할

1. 전역 상태 관리 흐름

const [value, setValue] = useState(‘hello‘);
const onSetValue = useCallback(value => setValue(value), []);
  • 기존 : 최상위 컴포넌트에서 여러 컴포넌트를 거쳐 props 전달
  • Context API를 사용하면 Context를 만들어 단 한 번에 원하는 값을 받아 와서 사용 가능함.

2. 실습

2.1. context 생성

React.createContext() : context 생성

import React from "react";

const ColorContext = React.createContext({color:'black'});
export default ColorContext;
  • 파라미터 : 해당 context의 기본 상태 지정(값 따로 지정 안 할 경우 사용될 값)

2.2. Consumer

import React from "react";
import ColorContext from "./color";

const ColorBox = () => {
  return (
    <ColorContext.Consumer>
      {(value) => (
        <div
          style={{
            width: "64px",
            height: "64px",
            background: value.color
          }}
        />
      )}
    </ColorContext.Consumer>
  );
};
export default ColorContext;
  • ColorContext 안에 있는 Consumer라는 컴포넌트를 이용하여 value값 조회
  • function as a child, Render Props라고도 함

* Render Props

  • react component 간 코드를 공유하기 위해 함수 props 이용
  • 무엇을 렌더링할지 컴포넌트에게 알려주는 함수
import React from ‘react‘;


const RenderPropsSample = ({ children }) => {
  return <div>결과: {children(5)}</div>;
};


export default RenderPropsSample;

//App.js
<RenderPropsSample>{value => 2 * value}</RenderPropsSample>;
  • props 로 함수를 전달함.

2.3. Provider

context를 구독하는 컴포넌트들에게 context의 변화를 알림

import React from "react";
import ColorContext from "./context/color";
import ColorBox from "./context/colorBox";

const App = () => {
  return (
    <ColorContext.Provider value={{ color: "red" }}>
      <div>
        <ColorBox />
      </div>
    </ColorContext.Provider>
  );
};

export default App;
  • Context 내 Provider라는 컴포넌트를 통해 값 변경 가능(value이용)
  • Provider 사용 시 value 값 명시하지 않으면 오류!!

3. 동적 Context

Color.js

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

const ColorContext = createContext({
  state: { color: "black", subcolor: "red" },
  action: {
    setColor: () => {},
    setSubColor: () => {}
  }
});

const ColorProvider = ({ children }) => {
  const [color, setColor] = useState("black");
  const [subcolor, setSubColor] = useState("red");

  const value = {
    state: { color, subcolor },
    action: { setColor, setSubColor }
  };
  return (
    <ColorContext.Provider value={value}>{children}</ColorContext.Provider>
  );
};

const {Consumer:ColorConsumer} = ColorContext;
export {ColorProvider, ColorConsumer};

export default ColorContext;
  • const ColorConsumer = ColorContext.Consumer 라는 의미(비구조화 할당)
  • value에서 state와 함수를 모두 묶어서 내보내줌.

비구조화 할당

const animal = {
  name: '멍멍이',
  type: '개'
};

const { name: nickname } = animal
  • animal 객체 안에 있는 name을 nickname으로 선언하겠다는 의미

App.js

import React from "react";
import ColorContext, { ColorProvider } from "./context/color";
import ColorBox from "./context/colorBox";

const App = () => {
  return (
    <ColorProvider>
      <div>
        <ColorBox />
      </div>
    </ColorProvider>
  );
};

export default App;

ColorBox.js

import React from "react";
import ColorContext, { ColorConsumer } from "./color";

const ColorBox = () => {
  return (
    <ColorConsumer>
      {(value) => (
        <>
          <div
            style={{
              width: "64px",
              height: "64px",
              background: value.state.color
            }}
          />
          <div
            style={{
              width: "64px",
              height: "64px",
              background: value.state.subcolor
            }}
          />
        </>
      )}
    </ColorConsumer>
  );
};
export default ColorBox;
  • ColorBox 내 ColorContext.Consumer를 ColorConsumer로 수정
import React from "react";
import ColorContext, { ColorConsumer } from "./color";

const ColorBox = () => {
  return (
    <ColorConsumer>
      {({state}) => (
        <>
          <div
            style={{
              width: "64px",
              height: "64px",
              background: state.color
            }}
          />
          <div
            style={{
              width: "64px",
              height: "64px",
              background: state.subcolor
            }}
          />
        </>
      )}
    </ColorConsumer>
  );
};
export default ColorBox;
  • 객체 비구조화 할당을 하면 더 간단하게 state의 color값 표현 가능
  • value-state-color, subcolor 형태이므로, state를 파라미터로 받을 경우엔, {} 표시를 하여 객체 형태임을 알려줘야 함.

3.1. 색상 선택 컴포넌트 만들기

selectColors.js

import React from "react";
import { ColorConsumer } from "./color";

const colors = ["red", "orange", "yellow", "green", "blue", "violet"];

const SelectColors = () => {
  return (
    <div>
      <h2>색상 선택</h2>
      <ColorConsumer>
        {({ action }) => (
          <div style={{ display: "flex" }}>
            {colors.map((color) => (
              <div
                key={color}
                style={{
                  background: color,
                  width: "24px",
                  height: "24px",
                  cursor: "pointer"
                }}
                onClick={() => action.setColor(color)}
                onContextMenu={(e) => {
                  e.preventDefault();
                  action.setSubColor(color);
                }}
              />
            ))}
          </div>
        )}
      </ColorConsumer>
      <hr />
    </div>
  );
};

export default SelectColors;
  • 왼쪽 버튼 클릭 시 color값이, 오른쪽 버튼 클릭(onContextMenu) 시 subColor 변경되도록 하는 컴포넌트
  • e.preventDefault() : 우측 버튼을 누르면 나타나는 메뉴를 생략함.

4. useContext Hook

ColorBox.js

import React, { useContext } from "react";
import ColorContext, { ColorConsumer } from "./color";

const ColorBox = () => {
  const { state } = useContext(ColorContext);

  return (
    <>
      <div
        style={{
          width: "64px",
          height: "64px",
          background: state.color
        }}
      />
      <div
        style={{
          width: "64px",
          height: "64px",
          background: state.subcolor
        }}
      />
    </>
  );
};
export default ColorBox;
  • ColorContext에서 state 객체 값만 받아서 이용함
profile
hello world!

0개의 댓글