React

contextAPI와 useContext 사용법 (다크모드 구현하기)

hihiha2 2023. 3. 15. 22:49

1️⃣ contextAPI와 useContext 사용이유

 

🤬 전역적인 정보들을  props로 전달하려면 단계별로 일일이 다 써주고, 수정시에도 불편하다. 🤬

전역적인 정보: User, 테마, 언어

 

 

✅  이럴때 사용하는 contextAPI, useContext ✅

 

리액트에서는 이러한 문제점을 해결하기 위해서 contextAPI를 제공한다.

context는 앱안에서 전역적으로 사용되는 데이터들을  여러컴포넌트끼리 쉽게 공유할 수 있는 방법을 제공한다.

 

➡️ 일일이 props로 제공하지 않아도 상위컴포넌트에서 전역적인 정보를 해당 컴포넌트로 바로 제공할 수 있어서 편리

 

 

 

 

 

2️⃣ useContext 사용법

🔫 다크모드 만들어보기 🔫

 

 

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값으로 넣어주었다.

 

🤩 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>
  );
}

 

 

 

 

<참고자료>

React Hooks에 취한다 - useContext+ContextAPI