[말로 풀어쓴 React] Context API

DongGu·2021년 1월 28일
1

목차

  • Context API를 사용한 전역 상태 관리 흐름 이해하기
  • 기본적인 사용법 익히기
  • 동적 Context 사용하기
  • Consumber 대신 Hook 또는 static contextType 사용하기

1. Context API를 사용한 전역 상태 관리 흐름 이해하기

  • 프로젝트 내에서 환경 설정, 사용자 정보와 같은 전역적으로 필요한 상태를 관리해야 할 때 어떻게 해야 할까?
  • 리액트 애플리케이션은 컴포넌트 간에 데이터를 props로 전달하기 때문에, 최상위 컴포넌트인 App의 state로 주로 관리한다!
  • 컴포넌트가 여러 개로 복잡할 땐, Context API를 사용해 여러 번 props로 전달하지 않고, "단 한 번"에 원하는 값을 받아와서 사용한다.

2. Context API 사용법 익히기

  • 1) 새 Context 만들기
    새 Context를 만들 때는 createContext 함수를 사용한다. createContext의 파라미터에는 해당 Context의 기본 상태를 지정한다.
// contexts/color.js
import {createContext} from 'react';
const ColorContext = createContext({color:'black'});
export default ColorContext;
  • 2) Consumer 사용하기
    Consumber 사이에 중괄호를 열어서 그 안에 함수({value => ()})를 넣었다. 이런 패턴을 Function as a child 혹은 Render Props라고 한다. 컴포넌트의 children이 있어야할 자리에 일반 JSX 혹은 문자열이 아닌 함수를 전달한다.
// components/CorlorBox.js
import React from 'react';
import ColorContext from '../contexts/color/';

const ColorBox = () => {
  return (
    <ColorContext.Consumer>
    	{value => (
         	<div
         		style = {{
         			width: '64px',
         			height: '64px',
         			background: value.color
                }}
			/>
		)}
    </ColorContext.Consumer>
  );
};

export default ColorBox;
  • 컴포넌트를 App에서 렌더링하기
import React from 'react';
import ColorBox from './components/ColorBox';
const App = () => {
  return (
    <div>
    	<ColorBox />
    </div>
  );
};
export deafult App;
- 참고: Render Props 예제
import React from 'react';
const RenderPropsSample = ({children}) => {
  return <div>결과: {children(5)} </div>;
}
export default RenderPropsSample;

위의 컴포넌트는 다음과 같이 사용 가능하다.
<RnderPropsSample>{value => 2*value}</RenderPropsSample>;

  • 3) Provider
    Provider를 사용하면 Context의 value를 바꿀 수 있다. Provider는 바꿀 값(value)를 명시해 줘야 한다.
import React from 'react';
import ColorBox from './components/ColorBox';
import ColorContext from './contexts/color';
const App = () => {
  return (
    <ColorContext.Provider value={{color:'red'}}>
    	<div>
    		<ColorBox />
    	</div>
	</ColorContext.Provider>
  );
};
export default App;	

3. 동적 Context 사용하기

  • 1) Context 파일 수정하기
    Context의 value에는 무조건 상태 값만 있어야 하는 것은 아니다. 함수를 전달해 줄 수도 있다.
// contexts/color.js
import React, { createContext, useState } from "react";

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

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

  const value = {
    state: { color, subcolor },
    actions: { setColor, setSubcolor },
  };

  return (
    <ColorContext.Provider value={value}>{children}</ColorContext.Provider>
  );
};
// const Colorconsumer = ColorContext.Consumer
const { Consumer: ColorConsumer } = ColorContext;

// ColorProvider와 ColorConsumber 내보내기
export { ColorProvider, ColorConsumer };

export default ColorContext;

const {Consumer: ColorConsumer} = ColorContext 비구조화 할당 이해 안됨

2) 새로워진 Context를 프로젝트에 반영하기

// App.js
import React from "react";
import ColorBox from "./components/ColorBox";
import ColorContext from "./contexts/color";

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

export default App;
  • 2) 새로워진 Context를 프로젝트에 반영하기
// App.js
import React from "react";
import ColorBox from "./components/ColorBox";
import { ColorProvider } from "./contexts/color";

const App = () => {
  return (
    <ColorProvider value={{ color: "red" }}>
      <div>
        <SelectColors />
    </div>
    </ColorProvider>
  );
};

export default App;
// components/ColorBox.js
import React from "react";
import { ColorConsumer } from "../contexts/color";

const ColorBox = () => {
  return (
    <ColorConsumer>
      {(value) => (
        <>
          <div
            style={{
              width: "64px",
              height: "64px",
              background: value.state.color,
            }}
          />
          <div
            style={{
              width: "32px",
              height: "32px",
              background: value.state.subcolor,
            }}
          />
        </>
      )}
    </ColorConsumer>
  );
};

export default ColorBox;
  • 3) 색상 선택 컴포넌트 만들기
// components/SelectColors.js
import React from "react";
import { ColorConsumer } from "../contexts/color";

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

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

export default SelectColors;
// App.js
import React from "react";
import ColorBox from "./components/ColorBox";
import { ColorProvider } from "./contexts/color";
import SelectColors from "./components/SelectColors";
const App = () => {
  return (
    <ColorProvider value={{ color: "red" }}>
      <div>
        <SelectColors />
        <ColorBox />
      </div>
    </ColorProvider>
  );
};

export default App;

4. Consumer 대신 Hook 또는 static contextType 사용하기

  • 1) useContext Hook 사용하기
// components/ColorBox.js
import React, { useContext } from "react";
import ColorContext from "../contexts/color";

const ColorBox = () => {
  const { state } = useContext(ColorContext);
  return (
    <>
      <div
        style={{
          width: "64px",
          height: "64px",
          background: state.color,
        }}
      />
      <div
        style={{
          width: "32px",
          height: "32px",
          background: state.subcolor,
        }}
      />
    </>
  );
};
export default ColorBox;
  • 2) static contextType 사용하기
    클래스형 컴포넌트에서 Context를 쉽게 쓰고 싶으면 static contextType을 정의하는 방법이 있다. SelectColors 컴포넌트를 다음과 같이 클래스형으로 변환해 보자. Consumer 코드는 일단 제거한다.
import React, { Component } from "react";
import ColorContext from "../contexts/color";

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

class SelectColors extends Component {
  static contextType = ColorContext;

  handleSetColor = (color) => {
    this.context.actions.setColor(color);
  };

  handleSetSubColor = (subcolor) => {
    this.context.actions.setSubcolor(subcolor);
  };
  render() {
    return (
      <div>
        <h2>색상을 선택하세요</h2>
        <div style={{ display: "flex" }}>
          {colors.map((color) => (
            <div
              key={color}
              style={{
                background: color,
                width: "24px",
                height: "24px",
                cursor: "pointer",
              }}
              onClick={() => this.handleSetColor(color)}
              onContextMenu={(e) => {
                e.preventDefault();
                this.handleSetSubColor(color);
              }}
            />
          ))}
        </div>
        <hr />
      </div>
    );
  }
}

export default SelectColors;
profile
코딩하는 신방과생

0개의 댓글