참고: https://www.youtube.com/watch?v=LwvXVEHS638&list=PLZ5oZ2KmQEYjwhSxjB_74PoU6pmFzgVMO&index=5
https://react.dev/reference/react/useContext 이문서를 봐라. 모든게 여기서 부터 시작하고 여기서 부터 끝난다. 이거 해석하면 매번 두려움에 떨지 않아도 된다.
1️⃣ contextAPI와 useContext 사용이유
🤬 전역적인 정보들을 props로 전달하려면 단계별로 일일이 다 써주고, 수정시에도 불편하다. 🤬
전역적인 정보: User, 테마, 언어
✅ 이럴때 사용하는 contextAPI, useContext ✅
리액트에서는 이러한 문제점을 해결하기 위해서 contextAPI를 제공한다.
context는 앱안에서 전역적으로 사용되는 데이터들을 여러컴포넌트끼리 쉽게 공유할 수 있는 방법을 제공한다.
➡️ 일일이 props로 제공하지 않아도 상위컴포넌트에서 전역적인 정보를 해당 컴포넌트로 바로 제공할 수 있어서 편리
2️⃣ useContext 사용법
useContext란? context로 공유한 데이터들을 쉽게 받아올수 있도록 도와주는 훅
🔫 다크모드 만들어보기 🔫
1. contex이름.js 파일을 생성한다.
ThemeContext.js이름으로 생성함
2. createContext를 import해주기
import {createContext} from 'react';
만들어준 파일의 상단에 import해준다.
3. context 생성하기
export const ThemeContext = createContext(초기값);
✔️ 여기까지가
①ThemeContext라는 이름을 가진,
②전역에서 사용할,
context를 js파일로 생성한것.✔️
4. ThemeContext를 사용하고 싶은 곳에 import 해주기
import { ThemeContext } from './ThemeContext';
5. 사용하고 싶은곳을 ThemeContext로 감싸주기
return (
<ThemeContext.Provider>
<Page/>
</ThemeContext.Provoder>
);
<Page>라는 컴포넌트의 하위부터 사용할 계획이라서 <Page>를 감쌌다.
6. context의 provider는 value라는 prop을 받는다.
이 value안에는 전달하고자 하는 데이터를 넣어준다.
const [isDark, setIsDark] = useState(false);
return (
<ThemeContext.Provider value={{isDark, setIsDark}}>
<Page />
</ThemeContext.Provoder>
)
isDark, setIsDark를 내려보내주고 싶어서 value값으로 넣어주었다.
이렇게 ThemeContext가 감싼 그 아래있는 모든 하위 컴포넌트는 isDark, setIsDark에 props사용없이 접근할 수 있게 됩니다.
🤩 Page 컴포넌트안에 넣어줬던 props인isDark={isDark} setIsDark={setIsDark}는 이제 지워줘도 된다. (원래 적어놓았다면)
(page컴포넌트는 정보가 필요한 당사자는 아님! ➡️ 하위컴포넌트중 props가 필요한 곳에서 바로 받아오면 된다)
7. useContext 훅을 사용해서 받아오기
7-1.
각각 파일의 상단에 useContext와 ThemeContext를 import해주어야한다.
7-2. useContext해주기
📚 isDark가 필요한 Header와 Content
const { isDark } = useContext(ThemeContext);
📚 isDark, SetIsDark가 필요한 Footer
const { isDark, setIsDark } = useContext(ThemeContext);
끝!!
👍 중간컴포넌트에서는(여기서는 Page컴포넌트) props를 안써도 된다. 👍
짜잔!! 다크모드가 구현되었다.
전체적인 코드를 아래와 같다.
//ThemeContext.js
import { createContext } from "react";
export const ThemeContext = createContext(null);
//App.js
import React, { useState } from "react";
import "./App.css";
import Page from "./Page";
import { ThemeContext } from "./ThemeContext";
export default function App() {
const [isDark, setIsDark] = useState(false);
return (
<ThemeContext.Provider value={{ isDark, setIsDark }}>
<Page />;
</ThemeContext.Provider>
);
}
//Page.js
import React from "react";
import Header from "./Header";
import Content from "./Content";
import Footer from "./Footer";
export default function Page() {
return (
<div className="page">
<Header />
<Content />
<Footer />
</div>
);
}
//Header.js
import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
export default function Header() {
const { isDark } = useContext(ThemeContext);
return (
<header
className="header"
style={{
backgroundColor: isDark ? "black" : "lightgrey",
color: isDark ? "white" : "black",
}}
>
<h1>모드 테스트중!!!</h1>
</header>
);
}
//Content.sj
import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
export default function Content() {
const { isDark } = useContext(ThemeContext);
return (
<div
className="content"
style={{
backgroundColor: isDark ? "black" : "white",
color: isDark ? "white" : "black",
}}
>
<p>화이팅 화이팅 화이팅 🔥</p>
</div>
);
}
//Footer.js
import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
export default function Footer() {
const { isDark, setIsDark } = useContext(ThemeContext);
const onToggle = () => {
setIsDark(!isDark);
};
return (
<footer
className="footer"
style={{
backgroundColor: isDark ? "black" : "white",
color: isDark ? "white" : "black",
}}
>
<button className="button" onClick={onToggle}>
Mode Change
</button>
</footer>
);
}
위의 context를 사용하지 않고 순전히 props, state를 사용하여 만든 코드(아래)
//Content.jsx
import React from "react";
const Content=({isDark})=>{
return (
<div className="content"
style={{background:isDark?'black':'white',
color:isDark?'white':'black',}}>
<p>홍길동님, 좋은 하루되세요</p>
</div>
);
};
export default Content;
//Footer.jsx
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;
//Header.jsx
import React from "react";
//부모 컴포넌트(Page)로부터 물려받은 props(isDark)
const Header=({isDark})=>{
return(
<header
className="header"
style={{backgroundColor:isDark?'black':'lightgray', color:isDark?'white':'black',}}
>
<h1>Welcome 홍길동</h1>
</header>
);
};
export default Header;
//Page.jsx
import React from 'react';
import Content from './Content';
import Footer from './Footer';
import Header from './Header';
//부모컴포넌트(App)에서 받은 props를
const Page=({isDark, setIsDark})=>{
return(
<div className="page">
{/* 자식컴포넌트(Header, Footer, Content)에게 전달하고 있다. props drilling이 발생하고 있음 */}
<Header isDark={isDark}/>
<Content isDark={isDark}/>
<Footer isDark={isDark} setIsDark={setIsDark}/>
</div>
);
};
export default Page;
//App.js
import { useState } from "react";
import './App.css';
import Page from './components/Page';
const App=()=>{
const [isDark, setIsDark]=useState(false);
//자식 컴포넌트(Page)에게 props로 상태를 넘기고 있다.
return <Page isDark={isDark} setIsDark={setIsDark}></Page>
}
export default App;
//index.css에 올릴 코드는 https://codepen.io/Coding-Star/pen/MWELozJ 여기에
'FrontEnd > React' 카테고리의 다른 글
React Hooks - React.memo로 컴포넌트 최적화하기 (useMemo, useCallback) (0) | 2024.03.28 |
---|---|
React Hooks - useCallback (실습포함) (0) | 2024.03.28 |
React Hooks -useEffect와 useRef를 이용한 간단한 프로그램만들기 (0) | 2024.03.27 |
React Hooks -useEffect에 대하여 (0) | 2024.03.27 |
React Hooks -useRef에 대하여(3) ref객체와 일반변수와의 다른점. ref를 사용하기 좋은 경우 (0) | 2024.03.27 |