참고한 영상: 별코딩님의 'React Hooks에 취한다 - useContext + Context API | 리액트 훅스 시리즈'
- context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있습니다.
- context는 React 컴포넌트 트리 안에서 전역적(global)이라고 볼 수 있는 데이터를 공유할 수 있도록 고안된 방법입니다.
- context의 주된 용도는 다양한 레벨에 네스팅된 많은 컴포넌트에게 데이터를 전달하는 것입니다.
- 출처 : Context - React 공식 문서
키워드 | 내용 |
---|---|
컴포넌트 트리 제약 | Props drilling의 한계 해소 |
재사용성 | Context를 사용하면 재사용하기 어려움 |
API | createContext/Provider/Consumer |
useContext | Consumer 대체 |
props 를 전달할 때는 부모컴포넌트가 자식 컴포넌트에게 일일이 props를 넣어서 단계별로 전달을 해줘야 한다.
Global Data를 자식들에게 전달해야하는 상황에 일일이 전달을 하려면 코드도 복잡해지고 props를 수정해줘야할 때 전부 다 바꿔줘야하는 문제점이 있다.
App이 Data props를 C와 E에게 전달해줘야 할 때
우선 A와 B에게 props를 전달하고 그리고 C 와 D, 그리고 E에게 전달할 수 있다.
App이 context를 통해 방송을 하게 되고, 아래와 같이 useContext hook을 이용하여 필요한 Data를 받아올 수 있다!
Context는 꼭 필요할 때만 !
- Context를 사용하면 컴포넌트를
재사용하기 어려워질 수 있다
- Prop drilling을 피하기 위한 목적이라면
Componenet Composition (컴포넌트 합성)
을 먼저 고려해보자
// App.js
import "./styles.css";
import React, { useState } from "react";
import Page from "./components/Page";
export default function App() {
const [isDark, setIsDark] = useState(false);
return <Page isDark={isDark} setIsDark={setIsDark} />;
}
// Page.js
import React from "react";
import Content from "./Content";
import Footer from "./Footer";
import Header from "./Header";
const Page = ({ isDark, setIsDark }) => {
return (
<div className="page">
<Header isDark={isDark} />
<Content isDark={isDark} />
<Footer isDark={isDark} setIsDark={setIsDark} />
</div>
);
};
export default Page;
// Header.js
import React from "react";
const Header = ({ isDark }) => {
return (
<header
className="header"
style={{
backgroundColor: isDark ? "black" : "lightgray",
color: isDark ? "white" : "black"
}}
>
<h1>Welcome 홍길동!</h1>
</header>
);
};
export default Header;
// Content.js
import React from "react";
const Content = ({ isDark }) => {
return (
<div
className="content"
style={{
backgroundColor: isDark ? "black" : "white",
color: isDark ? "white" : "black"
}}
>
<p>홍길동님, 좋은 하루 되세요</p>
</div>
);
};
export default Content;
// Footer.js
import React from "react";
const Footer = ({ isDark, setIsDark }) => {
const toggleTheme = () => {
setIsDark(!isDark);
};
return (
<footer
className="footer"
style={{
backgroundColor: isDark ? "black" : "lightgray"
}}
>
<button className="button" onClick={toggleTheme}>
Dark Mode
</button>
</footer>
);
};
export default Footer;
App에서 useState hook을 사용하여 isDark state 생성하고 자식 컴포넌트에서 isDark를 사용하기 위해 props를 개별적으로 전달
가장 먼저, context 폴더를 만들고 그 안에 ThemeContext.js
파일을 만든다.
1️⃣ createContext
import 해온다.
2️⃣ createContext를 사용하여 ThemeContext를 만든다.
import { createContext } from 'react';
export const ThemeContext = createContext(null);
App 컴포넌트로 가서 위에서 생성한 context를 import 한다.
// App.js
import "./styles.css";
import React, { useState } from "react";
import Page from "./components/Page";
import { ThemeContext } from "./context/ThemeContext";
export default function App() {
const [isDark, setIsDark] = useState(false);
return (
<ThemeContext.Provider value={{ isDark, setIsDark }}>
<Page />)
</ThemeContext.Provider>
);
}
3️⃣ Provider
를 사용하여 value={{ isDark, setIsDark}}
필요한 사람~ 하고 방송한다.
// Header.jsx
import React, { useContext } from "react";
import { ThemeContext } from "../context/ThemeContext";
const Header = () => {
const { isDark } = useContext(ThemeContext);
console.log(isDark);
return (
<header
className="header"
style={{
backgroundColor: isDark ? "black" : "lightgray",
color: isDark ? "white" : "black"
}}
>
<h1>Welcome 홍길동!</h1>
</header>
);
};
export default Header;
4️⃣ isDark가 필요한 Header
와 Content
는 useContext
를 사용하여 받아온다.
const { isDark } = useContext(ThemeContext);
5️⃣ isDark와 setIsDark 가 필요한 Footer
도 useContext
를 사용하여 받아온다.
const { isDark, setIsDark } = useContext(ThemeContext);
// ThemeContext.js
import { createContext } from 'react;
export const ThemeContext = createContext(null);
createContext(초기값) 을 설정할 수 있다.
만약 상위 컴포넌트에서 Provider로 감싸주지 않아서 value값이 없는 상태
라고 하면 설정한 초기값이 사용된다.
// ThemeContext.js
import { createContext } from 'react;
export const ThemeContext = createContext('메롱');
// Page.js
// ...생략...
const data = useContext(ThemeContext);
console.log(data);
// ...생략...
// console.log(data) 출력결과
'메롱'
홍길동이 아닌 '사용자'라는 userContext 를 생성하여 필요한 곳에 사용해보자!!
정답