1. useContext
리액트의 데이터는 일반적으로 '부모 컴포넌트 → 자식 컴포넌트' 로 단방향 흐름이다.
여러 컴포넌트들의 트리에서 전역으로 사용하는 데이터가 있을때 단방향으로 props를 단계별로 넘기는 것은 비효율적이고, 코드가 복잡해질 수 있다.
이러한 문제를 해결하기 위해 전역적으로 상태를 관리를 관리할 때 사용하는 훅(Hook)이 useContext() 이다.
function Component() {
const theme = useContext(ThemeContext);
...
}
위 코드는 useContext() 를 호출하여 Context를 구독하는 예제이다.
useContext() 에 createContext() 로 생성항 Context 객체를 전달하면, Context 에서 제공하는 값을 반환하게 된다.
이렇게 반환된 값은 Context Provider 의 모든 하위 컴포넌트들에서 사용할 수 있고,
이 값이 변경되면 Context Provider 의 모든 하위 컴포넌트들은 자동으로 리렌더링이 발생하는 것이다.
2. 사용 방법
1. Context 생성
const TestContext = createContext();
2. Provider 로 감싸기
function App() {
return (
<TestContext.Provider value="test">
<ChildComponent1 />
<ChildComponent2 />
<ChildComponent3 />
<TestContext.Provider />
);
}
3. useContext 호출로 값 사용
function ChildComponet1() {
const value = useContext(TestContext);
return <p>{value}</p>;
}
3. 예제
나는 Context 관련 로직을 하나의 Provider로 만들었는데, 아래와 같은 이점으로 재사용성과 가독성이 향상된다고 생각한다.
- Context 관련 로직을 Provider 컴포넌트에서 모두 확인이 가능
- Context 를 사용하는 하위 컴포넌트에서 useContext() 만 호출하면 값을 사용 가능
1. Provider 컴포넌트 생성
// ThemeProvider.tsx
// Context 생성
const ThemeContext = createContext();
// Provider
const ThemeProvider = ({children}) => {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
export default ThemeProvider;
// Custom Hook
export const useThemeContext = () => {
const context = useContext(ThemeContext);
if (!context) throw new Error("useThemeContext는 ThemeProvider 내에서 사용해야 합니다.");
return context;
}
2. Provider 감싸기
function App() {
return (
<ThemeProvider>
<Header />
<Main />
<Footer />
</ThemeProvider>
);
}
3. Custom Hook 으로 Context 값을 Provider로 감싼 하위 컴포넌트에서 사용
function Header() {
const { theme, setTheme } = useThemeContext();
const changeTheme = () => {
setTheme((prev) => prev === "light" ? "dark" : "light");
};
return (
<div>
<p>Current Theme : {theme}</p>
<button onClick={changeTeheme}>Chagne Theme</button>
</div>
);
}
4. Header 컴포넌트에서 Context 값이 변경되면, 해당 Context 값을 읽는 컴포넌트들을 리렌더링