React에서 자식 컴포넌트에게 데이터를 전달하기 위해 사용하는 props는
깊이가 깊어질수록 같은 값을 계속 내려줘야한다. 이를 prop drilling이라고 부른다.
// App.js
function App() {
const theme = "dark";
return <Layout theme={theme} />;
}
export default App;
// Layout.js
function Layout({ theme }) {
return (
<div>
<Home theme={theme} />
</div>
);
}
export default Layout;
// Home.js
function Home({ theme }) {
return <div>현재 테마는 {theme} 입니다.</div>;
}
export default Home;
하지만 prop drilling은 깊이가 길어질수록 가독성이 떨어지고
데이터가 필요없는 중간 컴포넌트도 자식 컴포넌트에게 데이터를 넘겨주기 위해 데이터를 받아야되는 문제가 있다.

위 예시에서도 Home에게 theme를 전달하기 위해 Layout도 theme 데이터를 받아야 한다.
useContext는 prop drilling을 하지 않고도 Context Provider에서 제공한 값을 컴포넌트 어디에서나 바로 사용할 수 있도록 하는 기능이다.

// ThemeContext.js
import {createContext} from 'react';
export const ThemeContext = createContext();
// App.js
import { ThemeContext } from "./ThemeContext";
function App() {
const theme = "dark";
return (
<ThemeContext.Provider value={theme}>
<Home />
</ThemeContext.Provider>
);
}
export default App;
useContext는 Provider로 감싸진 영역 내에서 Context를 공유합니다.
import { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
function Home() {
const theme = useContext(ThemeContext);
return <div>현재 테마는 {theme} 입니다.</div>;
}
export default Home;
const TextContext = createContext()
export default function App() {
const [text, setText] = useState("Hello world")
return (
<div>
<TextContext.Provider value={text}>
<Middle></Middle>
</TextContext.Provider>
</div>
)
}
useContext를 사용하면 context의 데이터가 필요 없는 곳에서는 context를 선언하지 않아도 됩니다.
function Middle(){
return (
<div>
<End/>
</div>
)
}
function End(){
const text = useContext(TextContext);
return (
<div>
{text}
</div>
)
}
useContext는 prop drilling 대신 데이터를 공유할 수 있는 좋은 방법이지만
provider의 값이 변경될 때마다 하위 컴포넌트가 재랜더링 됩니다.
때문에 다음에 공부해볼 memo와 병행하여 사용하면 더 좋은 성능을 볼 수 습니다.