Context API

์ „์—ญ์œผ๋กœ ์‚ฌ์šฉํ•  ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ

์˜ˆ์‹œ) ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ ์ •๋ณด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™˜๊ฒฝ ์„ค์ •, ํ…Œ๋งˆ React 16.3๋ถ€ํ„ฐ ์‚ฌ์šฉ๊ฐ€๋Šฅ

Redux, React Roter, styled-componrnts ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ Context API ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค.

Redux๋‚˜ MobX ๊ฐ™์€ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ ์ž‘์—…์„ ๋” ํŽธ๋ฆฌํ•˜๊ฒŒ ํ•˜๊ธฐ๋„ ํ•˜์ง€๋งŒ, React v16.3 ์—…๋ฐ์ดํŠธ ์ดํ›„์—๋Š” ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ์ „์—ญ ์ƒํƒœ๋ฅผ ์†์‰ฝ๊ฒŒ ๊ด€๋ฆฌ ํ•  ์ˆ˜ ์žˆ๋‹ค.

constexts/color.js

createContext

์ƒˆ Context๋ฅผ ๋งŒ๋“ค๋• createContext๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

import { createContext } from 'react';

const ColorContext = createContext({ color: 'black' });

export default ColorContext;

Consumer

ColorBox Component: ColorContext ์•ˆ์— ๋“ค์–ด ์žˆ๋Š” ์ƒ‰์ƒ์„ ๋ณด์—ฌ์คŒ props๋กœ ๋ฐ›์•„ ์˜ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ColorContext ์•ˆ์— ๋“ค์–ด ์žˆ๋Š” Consumer๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด ์ƒ‰์„ ์กฐํšŒ

src/components/ColorBox.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;

์•ˆ์— ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ฃผ๋Š” ํŒจํ„ด์„ Function as a child ํ˜น์€ Render Props ๋ผ๊ณ  ํ•œ๋‹ค. ์ปดํฌ๋„ŒํŠธ์˜ children์ด ์žˆ์–ด์•ผ ํ•  ์ž๋ฆฌ์— ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

Function as a child or Render Props

import React from 'react';

const RenderPropsSample = ({ children }) => {
  return <div>๊ฒฐ๊ณผ: {childern(5)}</div>;
};

// ๋งŒ์•ฝ ์œ„์™€ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด ์ถ”ํ›„ ์‚ฌ์šฉํ•  ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 
<RenderPropsSample>{value => 2 * value}</RenderPropsSample>

children์„ ํ•จ์ˆ˜๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ตฌ, ์ธ์ž๊ฐ’์„ ํ†ตํ•ด ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ตฌ๋‚˜. ํ—?!

children์„ ํ•จ์ˆ˜๋ผ ์ƒ๊ฐํ•˜๋‹ˆ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์›Œ์กŒ๋Œœ.

Provider

Context์˜ value๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

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

const ColorContext = createContext({ color: "black" }); Provider๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๋•Œ ๊ธฐ๋ณธ๊ฐ’

Provider๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” value๋ฅผ ๊ผญ ๋ช…์‹œํ•ด์ค˜์•ผ ํ•œ๋‹ค.

๋™์  Context ์‚ฌ์šฉ

contexts/color.js ์ˆ˜์ •

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

// ์ƒˆ Context๋ฅผ ๋งŒ๋“ค๋• createContext๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
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 { Consumer: ColorConsumer } = ColorContext;

export { ColorProvider, ColorConsumer };

export default ColorContext;

ColorProvider ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๊ณ , ๊ทธ ์ปดํฌ๋„ŒํŠธ๋Š” ColorContext.Provider๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค.

App.js์— ColorProvider์‚ฌ์šฉ

import { ColorProvider } from "./contexts/color";

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

export default App;

ColorBox ์ปดํฌ๋„ŒํŠธ์— ColorConsumer ์‚ฌ์šฉ

ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ์ปดํฌ๋„ŒํŠธ์ด๋‹ˆ Consumer์‚ฌ์šฉ

import ColorConsumer from "../contexts/color";

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

๊ฐ์ฒด ๋น„๊ตฌ์กฐํ™” ํ™œ๋‹น ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ value์—์„œ state๋งŒ ์กฐํšŒ

selectBox ์ถ”๊ฐ€

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",
              cursor: "pointer"
            }}
            onClick={() => actions.setColor(color)}
            onContextMenu={e => {
              e.preventDefault(); // ๋งˆ์šฐ์Šค ์˜ค๋ฅธ์ชฝ ํด๋ฆญ์‹œ ๋ฉ”๋‰ด๊ฐ€ ๋œจ๋Š” ๊ฒƒ์„ ๋ฌด์‹œํ•œ๋‹ค.
              actions.setSubcolor(color);
            }}
          />
        ))}
      </div>
      )}
      </ColorConsumer>
      <hr />
    </div>
  );
};

export default SelectColors;
  actions: {
    setColor: () => {},
    setSubcolor: () => {}
  }

์ฒ˜์Œ์— ์ด ๋ถ€๋ถ„์ด ์ดํ•ด๊ฐ€ ์•ˆ๊ฐ”๋Š”๋ฐ, ๊ทธ๋ƒฅ ์ด ์ž๋ฆฌ์— ํ•จ์ˆ˜๊ฐ€ ์˜ฌ ๊ฑฐ๋ผ๋Š” ๋œป์ด์˜€๋‹ค.

onContextMenu()๋Š” ๋งˆ์šฐ์Šค ์˜ค๋ฅธ์ชฝ ํด๋ฆญํ–ˆ์„๋•Œ ์‚ฌ์šฉ

useContext Hook ์‚ฌ์šฉํ•˜๊ธฐ

context๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ์—์„œ

<ColorConsumer>
  {({ state }) => (
    // code
  )}
</ColorConsumer>

ColorConsumer ์ปดํฌ๋„ŒํŠธ๋“ค ์ง€์šฐ๊ณ 

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
        }}
      />
    </>
  );
};

์•„์ฃผ ๊ฐ€๋ณ๊ณ  ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉ๊ฐ€๋Šฅ

Class Component์—์„œ static contextType ์‚ฌ์šฉํ•˜๊ธฐ

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>
    );
  }
}
 static contextType = ColorContext;

Class Component์—์„œ๋„ static contextType์„ ์ด์šฉํ•˜์—ฌ Context๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹จ์ ์€ ํ•œ class ์ปดํฌ๋„ŒํŠธ๋‹น ํ•˜๋‚˜์˜ Context๋ฐ–์— ์‚ฌ์šฉ๋ชปํ•œ๋‹ค.. ๐Ÿ˜•

์ •๋ฆฌ

๋‹จ์ˆœํ•œ ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๋Š” ๋ฆฌ๋•์Šค ๋Œ€์‹ ์— Context API๋กœ ๋Œ€์ฒด ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฆฌ๋•์Šค๋Š” ๋”์šฑ ํ–ฅ์ƒ๋œ ์„ฑ๋Šฅ๊ณผ ๋ฏธ๋“ค์›จ์–ด ๊ธฐ๋Šฅ, ๊ฐ•๋ ฅํ•œ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ, ์ฝ”๋“œ์˜ ๋†’์€ ์œ ์ง€ ๋ณด์ˆ˜์„ฑ์„ ์ œ๊ณต..

Last updated

Was this helpful?