오늘 TIL은 뭘 쓸까 하다가 이번 개인과제 마지막 단계에서 써야하는 훅 useContext
를 공부했다. 지금 props drilling
버전으로 과제 진행중인데 번거로워 죽을맛이다🤯🤯 (뭐.. useContext를 써도 못하겠지만 아무튼)
useContext
버튼을 누르면 다크모드로, 다시 누르면 원상태로 돌아오는 코드인데 이걸 useContext
로 구현해보았다.
import { createContext } from "react";
export const ThemeContext = createContext(null);
//null은 초기값!
useState
만들 때처럼 createContext
를 불러와야한다!
null
은 뭘까?만약에 Provider
로 감싸주지 않고 (value
로 어떤 값을 넘겨주지 않고) Page 컴포넌트로 가서 똑같이 useContext
불러온 후 콘솔을 확인하면 우리가 적었던 초기값 null
이 찍히는 걸 확인할 수 있다.
import { 내가 만든 context 파일명 } from "./context/파일명";
function App() {
return (
<div>
<Context파일명.Provider value={{넘겨줄 값(props로 넘겨줬던거)}}>
<Page /> // 이 안에 있는 모든 애들 useContext 영향 받음!
</Context파일명.Provider>
</div>
);
}
export default App;
🚧 App.jsx 컴포넌트
import "./styles.css";
import { useState } from "react";
import { ThemeContext } from "./context/ThemeContext";
import Page from "./components/Page";
function App() {
const [isDark, setIsDark] = useState(false);
return (
<div>
<ThemeContext.Provider value={{isDark, setIsDark}}>
<Page />
</ThemeContext.Provider>
</div>
);
}
export default App;
위 코드에서 쓰인 Provider
는 value
로 prop을 전달받는다 (여기서는 isDark
setIsDark
)
Provider
가 감싸는 모든 하위 컴포넌트들은 value
로 집어넣어준거에 접근할 수 있다.
props
를 사용하지 않고도!
🚧 Page.jsx 컴포넌트
import Content from "./Content";
import Header from "./Header";
import Footer from "./Footer";
const Page = () => {
// const data = useContext(ThemeContext);
// console.log(data); -> isDark:false 와 setIsDark가 객체 형태로 넘어감
return (
<div className="page">
<Header />
<Content />
<Footer />
</div>
);
};
export default Page;
App
컴포넌트에서 Page
컴포넌트에 prop
으로 직접 넘겨주지 않았음에도 useContext
를 확인해보면 prop으로 주었을 때처럼 데이터를 전달받은 걸 확인할 수 있다.
Page
컴포넌트는 다크모드의 영향을 전혀 받지 않기 때문에 prop으로 받아올게 없다. 받아온게 없기 때문에 하위컴포넌트인 Header
, Content
, Footer
컴포넌트에도 넘겨줄 게 없다.
🚧 Header.jsx 컴포넌트
import { useContext } from "react";
import { ThemeContext } from "../context/ThemeContext";
const Header = () => {
const { isDark } = useContext(ThemeContext);
return (
<header
className="header"
style={{
backgroundColor: isDark ? "black" : "lightgray",
color: isDark ? "white" : "black",
}}
>
<h1>Welcome 홍길동</h1>
</header>
);
};
export default Header;
Header 컴포넌트에서는 isDark
만 필요하기 때문에 ThemeContext
를 불러오기 위해 useContext
를 이용했다.
isDark
를 콘솔로 찍어보면 false
가 뜨는데 이걸 삼항연산자로 활용해서 다크버전 스타일을 만들었다.
🚧 Content.jsx 컴포넌트
import { useContext } from "react";
import { ThemeContext } from "../context/ThemeContext";
const Content = () => {
const { isDark } = useContext(ThemeContext);
return (
<div
className="content"
style={{
backgroundColor: isDark ? "black" : "lightgray",
color: isDark ? "white" : "black",
}}
>
<p>좋은 하루 되세요</p>
</div>
);
};
export default Content;
🚧 Footer.jsx 컴포넌트
import { useContext } from "react";
import { ThemeContext } from "../context/ThemeContext";
const Footer = () => {
const { isDark, setIsDark } = useContext(ThemeContext);
const toggleTheme = () => {
setIsDark(!isDark);
};
return (
<footer
className="footer"
style={{
backgroundColor: isDark ? "black" : "lightgray",
color: isDark ? "white" : "black",
}}
>
<button className="button" onClick={toggleTheme}>
Dark Mode
</button>
</footer>
);
};
export default Footer;
Content
와 Footer
에도 동일하게 useContext
를 사용해서 만들어주었다.
✅ 결과창 확인
const Footer = ({ isDark, setIsDark }) => {
//props로 넘겨받아오기
const toggleTheme = () => {
setIsDark(!isDark);
};
return (
<footer
className="footer"
style={{
backgroundColor: isDark ? "black" : "lightgray",
color: isDark ? "white" : "black",
}}
>
<button className="button" onClick={toggleTheme}>
Dark Mode
</button>
</footer>
);
};
export default Footer;
이렇게 prop
으로 전달하면 상위컴포넌트에도 계속해서 prop을 넘겨주는 코드가 필요하다ㅜ
Page
컴포넌트에서는 isDark
, setIsDark
가 필요하지 않았다.useContext
의 Provider
로 Page 컴포넌트
를 감싸주어 자식컴포넌트들에게 useContext
가 제공하는 속성 필요한 사람은 써! 라고 말해줌Header
, Content
, Footer
컴포넌트는 다크모드 속성이 필요하므로 useContext
를 import
해서 사용해주었다!Page
컴포넌트는 더이상 중간에서 prop을 연결해주는 불필요한 작업을 하지 않아도 됨!24.08.23 스탠다드반 보충수업 내용 추가!
출처