Frontend/React

리액트 context 사용하는 방법

전예방 2024. 1. 6. 22:59
✏️ context
context는 전역적으로 데이터를 관리할 수 있게 도와 줄 수 있는 리액트 Hook
부모 -> 자식 -> 손자 이런 구조로 되어있고, 부모에서 손자까지 데이터를 공유하고 싶은면 항상 차례대로 데이터를 전달해 줘야했는데 context를 사용하면 바로 부모 -> 손자로 넘겨줄 수 있다.

🔥 주의점
다양한 레벨에 네스팅된 많은 컴포넌트들에게 데이터를 전달하는 용도
context를 사용하면 컴포넌트를 재사용하기 어려워진다.

context 또는 컴포넌트 합성 둘 중에 더 상황에 맞는 것을 이용하도록!

 

나는 작업할 때

context 폴더를 만들어서 context를 관리하는 편!

 

응집도는 높이고, 결합도는 낮추기 위해 context 관련 소스는 해당 폴더, 해당 파일 안에서 관리하는 것이 좋은 것 같다. (아래에서 확인)

 

1. createContext

createContext를 이용해 context 객체를 생성해준다.

const ThemeContext = createContext();

defaultValue는 optional이다.

defaultValue는 트리 안에서 적절한 Provider를 찾지 못했을 때만 쓰이는 값이다.

 

2. Context.Provider

<ThemeContext.Provider value={{ mode : "light", toggleTheme }}>

<ThemeContext.Provider value="light">

Context 오브젝트의 Providersms context를 구독하는 컴포넌트에게 context의 변화를 알림

Provider가 value prop을 받아 이 값을 하위 컴포넌트들에게 전달해준다.

 

3. Context.Consumer

<ThemeContext.Consumer>
	{ value => /* context 값을 이용한 렌더링 */ }
</ThemeContext.Consumer>

Context의 변화를 감지해 value값에 접근할 수 있다.

 

Consumer은 아직 접해보지 못했는데...

useContext 대신 사용하는 용도인 것 같다.

 

4. useContext

const theme = useContext(ThemeContext);

하위 컴포넌트에서 쓰는 것이다.

파라미터로 Context를 넘기면 value 값을 읽어온다.

 

📄 ThemeContext

응집도는 높이고, 결합도는 낮추는 방법!

 

ThemeProvider와 useThemeMode만 외부 파일에서 사용하면된다.

수정은 ThemeContext.jsx파일 한개만 수정하면된다.

// 📄 context/ThemeContext.jsx

import { createContext, useContext, useEffect, useState } from "react";

export const ThemeContext = createContext();

export function ThemeProvider({ children }) {
  const [mode, setMode] = useState("light");
  const toggleTheme = () => {
	if(mode === 'light') {
        return "dark"
    } else {
    	return "light"
    }
    setMode(mode);
    updateTheme(mode);
  };

  useEffect(() => {
    const isDark =
      localStorage.theme === "dark" ||
      (!("theme" in localStorage) &&
        window.matchMedia("(prefers-color-scheme: dark)").matches);
	
    if(isDark) {
    	setMode("dark");
        updateTheme("dark");
    } else {
    	setMode("light");
        updateTheme("light");
    }
  }, []);

  return (
    <ThemeContext.Provider value={{ mode, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

function updateTheme(current) {
  if (current === "dark") {
    document.documentElement.classList.add("dark");
    localStorage.theme = "dark";
  } else {
    document.documentElement.classList.remove("dark");
    localStorage.theme = "light";
  }
}

export const useThemeMode = () => useContext(ThemeContext);

 

'Frontend/React'의 다른글

  • 현재글 리액트 context 사용하는 방법

관련글