React Hook - useContext

하영·2024년 8월 20일
1

React

목록 보기
8/17
post-custom-banner

오늘 TIL은 뭘 쓸까 하다가 이번 개인과제 마지막 단계에서 써야하는 훅 useContext 를 공부했다. 지금 props drilling 버전으로 과제 진행중인데 번거로워 죽을맛이다🤯🤯 (뭐.. useContext를 써도 못하겠지만 아무튼)

useContext

버튼을 누르면 다크모드로, 다시 누르면 원상태로 돌아오는 코드인데 이걸 useContext 로 구현해보았다.


context 폴더 만들고 파일 만들기

import { createContext } from "react";

export const ThemeContext = createContext(null);

//null은 초기값!

useState 만들 때처럼 createContext를 불러와야한다!


🙄 초기값 null 은 뭘까?

만약에 Provider로 감싸주지 않고 (value로 어떤 값을 넘겨주지 않고) Page 컴포넌트로 가서 똑같이 useContext 불러온 후 콘솔을 확인하면 우리가 적었던 초기값 null이 찍히는 걸 확인할 수 있다.


useContext 컴포넌트에서 불러오기

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;

위 코드에서 쓰인 Providervalue 로 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;

ContentFooter에도 동일하게 useContext를 사용해서 만들어주었다.


✅ 결과창 확인


❓props로만 내려준 형태의 코드 (useContext 사용X)

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을 넘겨주는 코드가 필요하다ㅜ



💡 정리!

  1. Page 컴포넌트에서는 isDark, setIsDark가 필요하지 않았다.
  2. 그래서 useContextProviderPage 컴포넌트를 감싸주어 자식컴포넌트들에게 useContext가 제공하는 속성 필요한 사람은 써! 라고 말해줌
  3. Header, Content, Footer 컴포넌트는 다크모드 속성이 필요하므로 useContextimport해서 사용해주었다!
  4. Page 컴포넌트는 더이상 중간에서 prop을 연결해주는 불필요한 작업을 하지 않아도 됨!

24.08.23 스탠다드반 보충수업 내용 추가!


출처

profile
왕쪼랩 탈출 목표자의 코딩 공부기록
post-custom-banner

0개의 댓글