✏️ 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' 카테고리의 다른 글
React에 CKEditor5 적용하기 (Online Builder) (0) | 2024.03.15 |
---|---|
react에서 alias가 상대경로로 지정 될 경우 (0) | 2024.01.15 |
[Deploy] Netlify 배포 Failed 해결방법 (0) | 2023.05.30 |
[Yarn] react에서 yarn berry (pnp) 에러 (0) | 2023.05.04 |
[React] 리액트 range slider 라이브러리 사용해서 range bar 만들기 (0) | 2023.04.26 |