[๐Ÿ’ŽReact] useContext

h-a-n-aยท2023๋…„ 3์›” 26์ผ
1

๐Ÿ’ŽReact

๋ชฉ๋ก ๋ณด๊ธฐ
11/14

useContext์˜ ๊ธฐ๋Šฅ

ํŠน์ •ํ•œ ๊ฐ’์„ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด๋†“๊ณ , ์–ด๋””์„œ๋“  ํŠน์ •ํ•œ ๊ฐ’์„ ๋ถˆ๋Ÿฌ์™€์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” Hook

๋ฆฌ์•กํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์œ„์—์„œ๋ถ€ํ„ฐ ์•„๋ž˜๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ด์ฃผ๋Š” ๊ตฌ์กฐ๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ๋‹ค. ๋งŒ์•ฝ ์–ด๋–ค ํ”„๋กœ์ ํŠธ์—์„œ ์ „์—ญ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ(user, theme, language ๋“ฑ)์ด ์žˆ๋‹ค๊ณ  ํ•˜์ž. ๊ทธ๋Ÿผ, ์ตœ์ƒ์œ„ App ์ปดํฌ๋„ŒํŠธ์—์„œ๋ถ€ํ„ฐ ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ € ์•„๋ž˜ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๊นŒ์ง€ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฑฐ์ณ๊ฐ€๋ฉฐ ์ „์†กํ•ด์ค˜์•ผ ํ•  ๊ฒƒ์ด๋‹ค. ๐Ÿคฌ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”์—†๋Š” ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ๋„ ์ „ํ•ด์ค˜์•ผํ•˜๋ฏ€๋กœ ์ฝ”๋“œ๋„ ๋ณต์žกํ•ด์งˆ๋ฟ๋”๋Ÿฌ, ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์—์„œ ์ผ์ผํžˆ ์ˆ˜์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.ใ… ใ… (props drilling)

useContext๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•„๊นŒ์ฒ˜๋Ÿผ ์ผ์ผํžˆ props ๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š์•„๋„ App ์ปดํฌ๋„ŒํŠธ๊ฐ€ "์ด ๋ฐ์ดํ„ฐ ํ•„์š”ํ•œ ์‚ฌ๋žŒ~?" ํ•˜๋ฉด ํ•ด๋‹น ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ๋งŒ ๋ฐ”๋กœ ์ „๋‹ฌํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

useState๋งŒ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•œ ํŽ˜์ด์ง€

App.jsx

function App() {
    const [isDark, setIsDark] = useState(false)
    return <Page isDark={isDark} setIsDark={setIsDark} />
}

Page.jsx

import React from 'react'

function Page({ isDark, setIsDark }) {
    return (
        <div>
            <Header isDark={isDark} />
            <Content isDark={isDark} />
            <Footer isDark={isDark} setIsDark={setIsDark} />
        </div>
    )
}

// ์ด ์•„๋ž˜๋Š” Page ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ปดํฌ๋„ŒํŠธ๋“ค
function Header({ isDark }) {
    return (
        <header style={{ background: isDark ? 'black' : 'lightgray', color: isDark ? 'white' : 'black' }}>
            <h1>ํ™๊ธธ๋™๋‹˜ ์•ˆ๋…•ํ•˜์„ธ์š”</h1>
        </header>
    )
}

function Content({ isDark }) {
    return (
        <div style={{ background: isDark ? 'black' : 'white', color: isDark ? 'white' : 'black' }}>
            <p style={{}}>์ข‹์€ ํ•˜๋ฃจ ๋˜์„ธ์š”</p>
        </div>
    )
}

function Footer({ isDark, setIsDark }) {
    const toggleTheme = () => {
        setIsDark(!isDark)
    }
    return (
        <div>
            <button onClick={toggleTheme}>๋‹คํฌ๋ชจ๋“œ/๋ผ์ดํŠธ๋ชจ๋“œ</button>{' '}
        </div>
    )
}
export default Page

์—ฌ๊ธฐ์„œ Page๋Š” isDark, setIsDark๋ฅผ ์ง์ ‘์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ์ € ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ์ „๋‹ฌ๋งŒ ํ•ด์ค„๋ฟ. ์ง€๊ธˆ์€ ์ค‘๊ฐ„ ์—ญํ• ์„ ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ Page ํ•˜๋‚˜๋ฟ์ด์ง€๋งŒ ํ”„๋กœ์ ํŠธ ๋‹จ์œ„๊ฐ€ ์ปค์ง€๋ฉด, ์ด๋Ÿฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ช‡ ์‹ญ๊ฐœ ๋  ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๐Ÿซ  ์ด์ œ๋ถ€ํ„ฐ useContext๋ฅผ ์‚ฌ์šฉํ•ด ์ข€ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ด๋ณด์ž!

useContext ์‚ฌ์šฉํ•ด ๊ตฌํ˜„ํ•œ ํŽ˜์ด์ง€

context ์ƒ์„ฑ
ThemeContext.js

import { createContext } from 'react'
export const ThemeContext = createContext(null)

์ƒ์„ฑํ•œ context.Provider๋ฅผ ํ†ตํ•ด์„œ ํŠน์ •ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ์ฃผ๋ฉด, value ๋ถ€๋ถ„์— ๋ช…์‹œํ•œ ๊ฐ’์„ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•ญ์ƒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.
App.jsx

import { ThemeContext } from './components/context/ThemeContext'
import Page from './components/Hooks/Page'

function App() {
    const [isDark, setIsDark] = useState(false)
    return (
        <ThemeContext.Provider value={{ isDark, setIsDark }}>
            <Page />
        </ThemeContext.Provider>
    )
}

Page.jsx

import React, { useContext } from 'react'
import { ThemeContext } from '../context/ThemeContext'

function Page() {
    return (
        <div>
            <Header />
            <Content />
            <Footer />
        </div>
    )
}

//ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ์•ž์„œ ๋งŒ๋“ค์–ด๋†“์€ context๋ฅผ ๋ถˆ๋Ÿฌ์˜จ ํ›„์—
//useContext๋ฅผ ์จ์ฃผ๋ฉด Provider์˜ value ๋ถ€๋ถ„์„ ํ†ตํ•ด์„œ ๋„˜๊ฒจ์ค€ ๊ทธ ๊ฐ’์„ ๋ฐ”๋กœ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค
function Header() {
    const { isDark } = useContext(ThemeContext)
    return (
        <header style={{ background: isDark ? 'black' : 'lightgray', color: isDark ? 'white' : 'black' }}>
            <h1>ํ™๊ธธ๋™๋‹˜ ์•ˆ๋…•ํ•˜์„ธ์š”</h1>
        </header>
    )
}

function Content() {
    const { isDark } = useContext(ThemeContext)

    return (
        <div style={{ background: isDark ? 'black' : 'white', color: isDark ? 'white' : 'black' }}>
            <p style={{}}>์ข‹์€ ํ•˜๋ฃจ ๋˜์„ธ์š”</p>
        </div>
    )
}

function Footer() {
    const { isDark, setIsDark } = useContext(ThemeContext)

    const toggleTheme = () => {
        setIsDark(!isDark)
    }
    return (
        <div>
            <button onClick={toggleTheme}>๋‹คํฌ๋ชจ๋“œ/๋ผ์ดํŠธ๋ชจ๋“œ</button>{' '}
        </div>
    )
}
export default Page

Page ์ปดํฌ๋„ŒํŠธ ์ž์ฒด๋Š” ๋” ์ด์ƒ isDark,setIsDark์— ๊ด€์—ฌํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ปดํฌ๋„ŒํŠธ๋“ค๋งŒ useContext,ThemeContext๋ฅผ importํ•ด์˜ค๋ฉด ๋œ๋‹ค.

์ด๋ ‡๊ฒŒ ๋ณด๋ฉด, useState๊ฐ€ ์•„๋‹Œ useContext๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ๋˜์ง€ ์•Š๋‚˜? ์ƒ๊ฐํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ, useContext๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค. ๋ฆฌ์•กํŠธ ๊ณต์‹๋ฌธ์„œ์—์„œ๋„ ๋‹จ์ง€ prop drilling ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ๋ผ๋ฉด, component composition ์„ ๊ถŒ์žฅํ•œ๋‹ค.
๊ฒฐ๋ก : ์ •๋ง๋กœ ์ „์ฒด ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ณต์œ ๋˜์–ด์•ผ ํ•˜๋Š” ๊ฐ’์ด ์žˆ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๊ณ , ๊ฐ ์ปดํฌ๋„ŒํŠธ๋ณ„๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ’์ด๋ผ๋ฉด useState๋ฅผ ์“ฐ๋Š” ๊ฒƒ์ด ์ ์ ˆํ•˜๋‹ค.


  • ์˜ค๋Š˜ ์•Œ๊ฒŒ ๋œ ์ :
    useContext๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์ „์ฒด ์ปดํฌ๋„ŒํŠธ์—์„œ ์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑธ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค.

  • ์˜ค๋Š˜ ๋ฐฐ์šด ๊ฒƒ ์ค‘ ๋” ์•Œ๊ณ  ์‹ถ๊ฑฐ๋‚˜ ๊ถ๊ธˆํ•œ ์ :
    ๊ทผ๋ฐ redux ์‚ฌ์šฉํ•˜๋ฉด ๋” ์ˆ˜์›”ํ•  ๊ฒƒ ๊ฐ™๋‹ค...? ์˜ค๋Š˜ ๊ณต๋ถ€ํ•˜๊ณ  redux TIL ๋„ ์ ์–ด์•ผ์ง€. ์ด์™ธ์—๋„ component composition ์— ๋Œ€ํ•ด ๋” ์•Œ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.
    ๋ฆฌ์•กํŠธ ๊ณต์‹๋ฌธ์„œ

  • ์˜ค๋Š˜์˜ ์†Œ๊ฐ:
    ๋ณด๋žŒ์ฐฌ ํ•˜๋ฃจ์˜€๋‹ค.

์œ ํŠœ๋ธŒ ๋ณ„์ฝ”๋”ฉ

profile
ํ•˜๋ฃจํ•˜๋ฃจ๊ฐ€ ์—ฐ์Šต์ด๋‹ˆ ๋‚ด์ผ์€ ๋” ๊ฐ•ํ•ด์งˆ ๊ฒ๋‹ˆ๋‹ค

0๊ฐœ์˜ ๋Œ“๊ธ€