Context

์ปจํ…์ŠคํŠธ๋Š” ๊ณต๊ธ‰์ž๊ฐ€ ์ƒˆ๋กœ์šด ๊ฐ’์„ ๊ฐ–๊ฒŒ ๋˜๋ฉด ๋ชจ๋“  ์ปจํ…์ŠคํŠธ ์†Œ๋น„์ž๋Š” ์ƒˆ๋กœ์šด ๊ฐ’์„ ๋ฐ›๊ณ  ๋ฆฌ๋ Œ๋”๋ง ๋œ๋‹ค.

์ปจํ…์ŠคํŠธ ์ „ํŒŒ์˜ ์ž‘๋™ ๋ฐฉ์‹

๋ฆฌ์•กํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜๋Š” ์ด์œ ๋Š” ๋‘ ๊ฐ€์ง€๋‹ค.

  1. ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜์—ˆ์„ ๋•Œ

  2. ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ

์ปจํ…์ŠคํŠธ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜๋Š”๋ฐ๋„ ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด, memo๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

memo๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๋Š” ์˜ˆ์ œ

const ColorContext = createContext('black')

const ColorComponent = () => {
    const color = useContext(ColorContext)

    // ๋žœ๋”๋ง ํšŸ์ˆ˜ ํ™•์ธ
    const renderCount = useRef(1)

    useEffect(()=> {
        renderCount.current += 1
    })

    return (
        <div style={{ color}}>
            Hello {color} (renders: {renderCount.current})
        </div>
    )
}

memo๋กœ ๊ฐ์‹ผ ColorComponent

const MemoizedColorComponent = memo(ColorComponent)

useContext๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ

const DummyComponent = () => {
    const renderCount = useRef(1);

    useEffect(() => {
        renderCount.current += 1;
    });

    return <div>Dummy (renders: {renderCount.current})</div>;
}

memo๋กœ ๊ฐ์‹ผ DummyComponent

const MemoizedDummyComponent = memo(DummyComponent)

๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง

const Parent = () => {
    <ul>
        <li><DummyComponent></li>
        <li><MemoizedDummyComponent></li>
        <li><ColorComponent></li>
        <li><MemoizedColorComponent></li>
    </ul>
}

App ์ปดํฌ๋„ŒํŠธ์—์„œ Parent ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง

const App = () => {
    const [color, setColor] = useState('red')
    return (
        <ColorContext.Provider value={color}>
             <input value={color} onChange={(e)=> setColor(e.target.value)} />
            <Parent />
        </ColorContext.Provider>
    )
}

์œ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด,

  1. ์ฒ˜์Œ์— ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋œ๋‹ค.

  2. ํ…์ŠคํŠธ ์ž…๋ ฅ ํ•„๋“œ์—์„œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋ฉด useState๋กœ ์ธํ•ด App ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋œ๋‹ค.

  3. ColorContext.provider๋Š” ์ƒˆ๋กœ์šด ๊ฐ’์„ ๋ฐ›๊ณ , Parent ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋œ๋‹ค.

  4. DummyComponent๋Š” ๋ฆฌ๋ Œ๋”๋ง ๋˜์ง€๋งŒ MemoizedDummyComponent๋Š” ๋ฆฌ๋ Œ๋”๋ง ๋˜์ง€ ์•Š๋Š”๋‹ค.

  5. ColorComponent๋Š” ๋‘ ๊ฐ€์ง€ ์ด์œ ๋กœ ๋ฆฌ๋ Œ๋”๋ง๋œ๋‹ค.

    • ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง ๋จ

    • ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ณ€๊ฒฝ ๋จ

  6. MemoizedColorComponent๋Š” ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ณ€๊ฒฝ๋๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ๋ Œ๋”๋ง๋œ๋‹ค.

memo๋ฅผ ์‚ฌ์šฉํ•ด๋„ ์ปจํ…์ŠคํŠธ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋ฆฌ๋ Œ๋”๋ง์„ ๋ง‰์„ ์ˆœ ์—†๋‹ค.

์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•œ ๋ชจ๋ฒ” ์‚ฌ๋ก€


// ์ดˆ๊ธฐ๊ฐ’์ด null์ธ ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ
type CountContextType = [
    number,
    Dispatch<SetStateAction<number>>
]

const Count1Context = createContext<CountContextType | null>(null)
// Count1Provider๋ฅผ ์ •์˜ํ•ด์„œ useState๋กœ ์ƒํƒœ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ปจํ…์ŠคํŠธ์— ์ œ๊ณต
export const count1Provider = ({
    children
}: {
    children: ReactNode 
}) => {
    <Count1Context.Provider value={useState(0)}>
        {children}
    </Count1Context.Provider>
}
// Count1Context์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ์ปค์Šคํ…€ ํ›…
export const useCount1 = () => {
    const value = useContext(Count1Context)
    if (value === null) throw new Error("Provider missing")
    return value
}
// Count2Context๋ฅผ ์ƒ์„ฑ
const Count2Context = createContext<CountContextType | null>(null)

export const Count2Provider = ({
    children
}: {
    children: ReactNode
}) => {
    <Count2Context.Provider value={useState(0)}>
        {children}
    </Count2Context.Provider>
}

export const useCount2 = () => {
    const value = useContext(Count2Context)
    if (value === null) throw new Error("Provider missing")
    return value
}
// count1์„ ์‚ฌ์šฉํ•˜๊ณ  ์นด์šดํŠธ์™€ ๋ฒ„ํŠผ์„ ๋ณด์—ฌ์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ
const Counter1 = () => {
    const [count1, setCount1] = useCount1()
    return (
        <div>
            Count1: {count1}
            <button onClick={() => setCount1((c) => c + 1)}>+1</button>
        </div>
    )
}
// count2๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์นด์šดํŠธ์™€ ๋ฒ„ํŠผ์„ ๋ณด์—ฌ์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ
const Counter2 = () => {
    const [count2, setCount2] = useCount2()

    return (
        <div>
            Count2: {count2}
            <button onClick={() => setCount2((c) => c + 1)}>+1</button>
        </div>
    )
}
const parent = () => {
    return (
        <div>
            <Counter1>
            <Counter1>
            <Counter2>
            <Counter2>
        </div>
    )
}
const App = () => {
    return (
        <Count1Provider>
            <Count2Provider>
                <Parent />
            </Count2Provider>
        </Count1Provider>
    )
}

Last updated