๐ฉ๐ป๐ป ์ธ์ ์ฌ์ฉํ๋์?
โ 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}
/>
);
}
ํด๋น ๋งํฌ์์ ์์ ์ฝ๋๋ฅผ ํ์ธํด๋ณด์ค ์ ์์ต๋๋ค
์ง๊ธ ๋ณด์๋ฉด 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
'React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ชจ๋ํ์ ๊ฐ๋ ๋ถํฐ Yarn Berry๊น์ง (0) | 2022.10.10 |
---|---|
npm, yarn, pnpm์ ์ฐจ์ด์ ์ ๋น๊ตํด๋ณด์ (0) | 2022.09.26 |
useEffect ์ ๋๋ก ์ดํดํ๊ธฐ (2) | 2022.09.21 |
Custom Hook์ ํจ์์ผ๊น ์ปดํฌ๋ํธ์ผ๊น (0) | 2022.09.09 |
react-hook-form ๋ก๋ฉ ํ๋ฉด ๋ง๋ค๊ธฐ (0) | 2022.08.22 |