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?