์žฌ๋ฐŒ๊ฒŒ ํ•ฉ์‹œ๋‹ค

๊ธฐ๋กํ•˜๊ธฐ, ๊ฐ€์‹œํ™”ํ•˜๊ธฐ

React

Context API ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ธฐ

์€๋˜๋”” 2022. 9. 22. 00:01

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?

โœ… React Component Tree์˜ ์„œ๋กœ ๋‹ค๋ฅธ ๋ถ€๋ถ„์—์„œ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”๋กœ ํ•  ๋•Œ

์œ„ ์ƒํ™ฉ์—์„œ ๋ณดํ†ต์€ props๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ๋ฐ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๊ฑฐ๋ฆฌ๊ฐ€ ๋จผ ๊ฒฝ์šฐ, ํŠน์ • ์ปดํฌ๋„ŒํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฑฐ์ณ์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

A
|
B
|
C
|
D

์œ„์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ์ด๋ค„์ง„ React Component Tree๋ฅผ ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค.

 

A: useState๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
D: A์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ UI๋ฅผ ๊ทธ๋ฆฌ๋Š” ์ปดํฌ๋„ŒํŠธ

๋ผ๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ, D์—๊ฒŒ A์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ฃผ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”? B,C๊ฐ€ props๋กœ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ(๊ฐ๊ฐ A,B)๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ ๋ฐ›๊ณ , ๋‹ค์‹œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ(๊ฐ๊ฐ C,D)์—๊ฒŒ props๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์ค˜์•ผ๊ฒ ์ฃ . ์‹ฌ์ง€์–ด B, C๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”๋กœ ํ•˜์ง€ ์•Š๋Š”๋ฐ๋„, ๋‹จ์ง€ D์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์ฃผ๊ธฐ ์œ„ํ•ด props๋ฅผ ๋ฐ›์•„ ์ „๋‹ฌํ•˜๋Š” ์ž‘์—…์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, D๊ฐ€ A์˜ ๋ฐ์ดํ„ฐ์— ๊ณง๋ฐ”๋กœ(B,C๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ณ ) ์ ‘๊ทผํ•˜๋„๋ก ํ•ด์ฃผ๋Š” ๊ฒŒ ๋ฐ”๋กœ Context API๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“‹ ๊ตฌ์„ฑ ์š”์†Œ

Context๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด ์„ธ ๊ฐ€์ง€์˜ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค!

CreateContext: Context๋ฅผ ์ƒ์„ฑ ํ•˜๋Š” ๊ฒƒ
Consumer Component: Context์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์™€์„œ ์‚ฌ์šฉ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
Provider Component: Context์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ

Context๋Š” ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ณต๊ฐ„์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Context๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„  ์šฐ์„  ์ด ๊ณต๊ฐ„์„ ๋งŒ๋“ค์–ด์ค˜์•ผ๊ฒ ์ฃ ! ์ด๊ฒŒ ๋ฐ”๋กœ 1๋ฒˆ createContext์ž…๋‹ˆ๋‹ค. createContext๋กœ ๊ณต๊ฐ„์„ ๋งŒ๋“ค์—ˆ๋‹ค๋ฉด, ์ด์ œ ์ด ๊ณต๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ , ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์™€์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค ๐Ÿ‘๐Ÿป๐Ÿ‘๐Ÿป๐Ÿ‘๐Ÿป ์œ„์˜ ์˜ˆ์‹œ์—์„œ๋Š” A๊ฐ€ Provider Component๊ฐ€ ๋˜๊ณ , D๊ฐ€ Consumer Component๊ฐ€ ๋˜๊ฒ ๋„ค์š”! ๊ทธ๋Ÿผ ์‹ค์ œ๋กœ Context๋ฅผ ์–ด๋–ป๊ฒŒ ๋งŒ๋“œ๋Š”์ง€, Provider Component์™€ Consumer Component์—์„œ ๊ฐ๊ฐ ์–ด๋–ค ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์ฝ์–ด์˜ค๋Š”์ง€๋ฅผ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹น.

๐Ÿ““ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

์˜ˆ์‹œ ์„ค๋ช…

์‰ฌ์šด ์ดํ•ด๋ฅผ ์œ„ํ•ด ์˜ˆ์‹œ๋ฅผ ํ•œ ๋ฒˆ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!
์•„๋ž˜ ์‚ฌ์ง„์ฒ˜๋Ÿผ, ์ƒ๋‹จ์˜ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํด๋ฆญํ•˜๋ฉด ์ด๋ฏธ์ง€์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ์ปค์ง€๋Š” ๊ธฐ๋Šฅ์ด ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค๊ณ  ํ•ด๋ด…์‹œ๋‹ค.

 


์ง  ์ด๋ ‡๊ฒŒ์š”

 

์œ„์˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ํ•œ ๋ฒˆ ์‚ดํŽด๋ณผ๊ฒŒ์š”.

import { useState } from 'react';
import { places } from './data.js';
import { getImageUrl } from './utils.js';

export default function App() {
  const [isLarge, setIsLarge] = useState(false);
  const imageSize = isLarge ? 150 : 100;
  return (
    <>
      <label>
        <input
          type="checkbox"
          checked={isLarge}
          onChange={e => {
            setIsLarge(e.target.checked);
          }}
        />
        Use large images
      </label>
      <hr />
      <List imageSize={imageSize} />
    </>
  )
}

function List({ imageSize }) {
  const listItems = places.map(place =>
    <li key={place.id}>
      <Place
        place={place}
        imageSize={imageSize}
      />
    </li>
  );
  return <ul>{listItems}</ul>;
}

function Place({ place, imageSize }) {
  return (
    <>
      <PlaceImage
        place={place}
        imageSize={imageSize}
      />
      <p>
        <b>{place.name}</b>
        {': ' + place.description}
      </p>
    </>
  );
}

function PlaceImage({ place, imageSize }) {
  return (
    <img
      src={getImageUrl(place)}
      alt={place.name}
      width={imageSize}
      height={imageSize}
    />
  );
}

ํ•ด๋‹น ๋งํฌ์—์„œ ์œ„์˜ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•ด๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

 

sandpack-project (forked) - CodeSandbox

sandpack-project (forked) by eunddodi using react, react-dom, react-scripts

codesandbox.io

์ง€๊ธˆ ๋ณด์‹œ๋ฉด App-List-Place-PlageImage ๊ตฌ์กฐ๋กœ Component Tree๊ฐ€ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋„ค์š”. ์‚ฌ์šฉ์ž์˜ ์ฒดํฌ๋ฐ•์Šค ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•ด์„œ imageSize๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฑด App ์ปดํฌ๋„ŒํŠธ์—์„œ ์ด๋ค„์ง€๊ณ  ์žˆ๊ณ , PlageImage ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•ด๋‹น ๊ฐ’์„ ์‚ฌ์šฉํ•ด UI๋ฅผ ๊ทธ๋ฆฌ๊ณ  ์žˆ์–ด์š”.

 

App์—์„œ PlageImage๊นŒ์ง€ imageSize ๊ฐ’์„ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด, imageSize ๊ฐ’์„ ์‚ฌ์šฉํ•˜์ง€๋„ ์•Š๋Š” List์™€ Place ์ปดํฌ๋„ŒํŠธ์— props๋กœ ํ•ด๋‹น ๊ฐ’์„ ์ „๋‹ฌํ•˜๊ณ  ์žˆ๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. ์•„์ฃผ ๋ฒˆ๊ฑฐ๋กญ์ฃ  ๐Ÿคฆ๐Ÿป‍โ™€๏ธ

 

์ด๋Ÿด ๋•Œ Context๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฑฐ์น  ํ•„์š” ์—†์ด App์—์„œ ์ €์žฅ(ํ˜น์€ ๋ณ€๊ฒฝ)ํ•œ imageSize๊ฐ’์„ PlaceImage ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ์„๊ฑฐ์˜ˆ์š”! ํ•œ ๋ฒˆ ์‚ฌ์šฉํ•ด๋ด…์‹œ๋‹ค.

 

Context ์ƒ์„ฑํ•˜๊ธฐ

์ƒˆ๋กœ์šด Context์˜ ์ƒ์„ฑ์€ ์ฃผ๋กœ ๋ณ„๋„์˜ ํŒŒ์ผ์—์„œ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
Context.js๋ผ๋Š” ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์„œ, ์•ˆ์— ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ค„๊ฒŒ์š”.

import { createContext } from 'react';

export const ImageSizeContext = createContext(500);

 

ImageSizeContext๋ผ๋Š” ์ด๋ฆ„์˜ ์ƒˆ๋กœ์šด context๋ฅผ ์ƒ์„ฑํ•˜๊ฒ ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ์ด์ œ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ImageSizeContext๋ฅผ importํ•˜๋ฉด ์ด context์•ˆ์— ๋‹ด๊ธด ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ , ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. createContext() ๊ด„ํ˜ธ ์•ˆ์— ๊ฐ’์„ ์ ์–ด์ฃผ๋ฉด, Context์˜ ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ์–ด์š”. ๋‹จ์ˆœ ์ˆซ์ž๋‚˜ string์ด ์•„๋‹Œ ๊ฐ์ฒด๋กœ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ต๋‹ˆ๋‹ค!

 

Use(consume) the Context

Context์— ์ €์žฅ๋œ ๊ฐ’์„ ์ฝ์–ด์˜ค๊ธฐ ์œ„ํ•ด์„œ๋Š”, useContext ๋ผ๋Š” Hook์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. imageSize ๊ฐ’์„ ํ•„์š”๋กœ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ์–ด๋””์ฃ ? PlaceImage ์ปดํฌ๋„ŒํŠธ์ฃ . ๊ฐ’์„ ํ•„์š”๋กœ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ useContext๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Context๋ฅผ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. useContext(MyContext) ๋ผ๋Š” ์ฝ”๋“œ๋Š”, React์—๊ฒŒ "๋‚˜ MyContext์˜ ์ •๋ณด๋ฅผ ์ฝ์–ด์˜ค๊ณ  ์‹ถ์–ด!"ํ•˜๊ณ  ์ด์•ผ๊ธฐํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

import { ImageSizeContext } from './Context.js';

function PlaceImage({ place }) {
  const imageSize = useContext(ImageSizeContext);
  return (
    <img
      src={getImageUrl(place)}
      alt={place.name}
      width={imageSize}
      height={imageSize}
    />
  );
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์•„๊นŒ createContext์— ์ €์žฅํ•ด๋‘” 500์ด๋ž€ ๊ฐ’์ด imageSize ๋ณ€์ˆ˜์— ๋‹ด๊ธฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Provide the Context

๊ทธ๋Ÿฌ๋‚˜ ์ €ํฌ๋Š” ์ง€๊ธˆ ์ด๋ฏธ์ง€ ์‚ฌ์ด์ฆˆ๋ฅผ 500์œผ๋กœ ์„ค์ •ํ•˜๊ณ  ์‹ถ์€ ๊ฒŒ ์•„๋‹ˆ๋ผ, ์‚ฌ์šฉ์ž๊ฐ€ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํด๋ฆญํ–ˆ๋Š”์ง€ ์•„๋‹Œ์ง€์— ๋”ฐ๋ผ ์ด๋ฏธ์ง€ ์‚ฌ์ด์ฆˆ๋ฅผ ๋ฐ”๊พธ๊ณ  ์‹ถ์€๊ฑฐ์ฃ . ๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„  App ์ปดํฌ๋„ŒํŠธ์—์„œ Context ๋‚ด์˜ imageSize๊ฐ’์„ ์—…๋ฐ์ดํŠธ ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. Conetext ์•ˆ์— ๋“ค์–ด์žˆ๋Š” Provider๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด Context์˜ value๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. <ImageContext.Provider value={imageSize}> ํƒœ๊ทธ๋กœ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ์ฃผ๋ฉด, ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋“ค์€ useContext๋ฅผ ํ†ตํ•ด ์œ„ ํƒœ๊ทธ์—์„œ ์ง€์ •ํ•œ value๋ฅผ ์ฝ์–ด์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

export default function App() {
  const [isLarge, setIsLarge] = useState(false);
  const imageSize = isLarge ? 150 : 100;
  return (
    <ImageSizeContext.Provider
      value={imageSize}
    >
      <label>
        <input
          type="checkbox"
          checked={isLarge}
          onChange={e => {
            setIsLarge(e.target.checked);
          }}
        />
        Use large images
      </label>
      <hr />
      <List />
    </ImageSizeContext.Provider>
  )
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด์ œ ์‚ฌ์šฉ์ž๊ฐ€ ์ฒดํฌ๋ฐ•์Šค๋ฅผ ํด๋ฆญํ•  ๋•Œ๋งˆ๋‹ค ImageSizeContext ๋‚ด์˜ value๊ฐ€ ์—…๋ฐ์ดํŠธ ๋ ๊ฑฐ๊ณ , PlaceImage ์ปดํฌ๋„ŒํŠธ๋Š” ์—…๋ฐ์ดํŠธ ๋œ value๋ฅผ ์ฝ์–ด์™€ ์ด๋ฏธ์ง€์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฒ ์ฃ ! ๋ฒˆ๊ฑฐ๋กœ์šด props ์ „๋‹ฌ ์—†์ด ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ƒˆ์–ด์š” ๐Ÿ‘๐Ÿป๐Ÿ‘๐Ÿป

(์ถ”๊ฐ€) Nested Provider

๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋“ค์€ ์ž์‹ ๊ณผ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด(React Component ํŠธ๋ฆฌ ์ƒ์—์„œ ์ˆ˜์ง-์œ„ ๋ฐฉํ–ฅ์œผ๋กœ) <Context.Provider> ์—์„œ ์ง€์ •ํ•œ value๋ฅผ ์ฝ์–ด์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ฐ€๋ น ์œ„ ์ฝ”๋“œ์™€ ๋™์ผํ•˜๊ฒŒ ์ž‘์„ฑํ•˜๋˜, ์•„๋ž˜์ฒ˜๋Ÿผ PlageImage ์ปดํฌ๋„ŒํŠธ์˜ ์ง๊ณ„ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์ธ Place ์ปดํฌ๋„ŒํŠธ์—์„œ <Context.Provider>๋กœ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ผ๋‹ค๋ฉด?

function Place({ place }) {
  return (
    <ImageSizeContext.Provider value={500}>
      <PlaceImage place={place} />
      <p>
        <b>{place.name}</b>
        {': ' + place.description}
      </p>
    </ImageSizeContext.Provider>
  );
}

์ด๋ฏธ์ง€ ํฌ๊ธฐ๋Š” 500์ด ๋ ๊ฒ๋‹ˆ๋‹ค. App ์ปดํฌ๋„ŒํŠธ์˜ <ImageContext.Provider> ๋ณด๋‹ค Place ์ปดํฌ๋„ŒํŠธ์˜ <ImgaeContext.Provider>๊ฐ€ PlaceImage์™€ ๋” ๊ฐ€๊น๊ธฐ ๋•Œ๋ฌธ์ด์ฃ .

 

๊ฐ Context๋Š” ๊ฐœ๋ณ„์ ์ด๋ฉฐ, ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ Context๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ๋™์ผํ•œ Context์˜ ๊ฒฝ์šฐ ์–ผ๋งˆ๋“ ์ง€ override๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

Context๋ฅผ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ ์ „๋ฌธ์€ ์—ฌ๊ธฐ์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค


Reference
https://beta.reactjs.org/learn/passing-data-deeply-with-context