The useContext Hook
Share data across a whole component tree without threading props through every level — the fix for prop-drilling.
When a value (the theme, the current user, a language) is needed by many components at different depths, passing it down as props through every layer — prop-drilling — gets painful. Context lets a parent broadcast a value to any descendant that asks for it.
#Three steps
import { createContext, useContext, useState } from 'react';
// 1. create the context
const ThemeContext = createContext('light');
function App() {
const [theme, setTheme] = useState('dark');
// 2. provide a value to the subtree
return (
<ThemeContext.Provider value={theme}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() { return <ThemedButton />; }
function ThemedButton() {
// 3. consume it — no props needed, at any depth
const theme = useContext(ThemeContext);
return <button className={theme}>I'm {theme}</button>;
}ThemedButton reads theme directly with useContext, even though Toolbar never received or passed it. Any component inside the Provider can grab the value.
Context isn't a state manager
Context handles distribution, not storage. You still hold the value in useState/useReducer and pass it (and its setters) as the Provider's value. Also, every consumer re-renders when the Provider's value changes — so don't put rapidly-changing, unrelated values in one big context.
What problem does Context primarily solve?
Key takeaways
- Context shares a value with a whole subtree without prop-drilling.
- Three steps: createContext, wrap with <Context.Provider value={...}>, read with useContext.
- Any descendant inside the Provider can consume the value at any depth.
- Context distributes data; you still store it in state. Consumers re-render when the value changes.
useContext returns the default 'light', ignoring the value the app set. Why?
const ThemeContext = createContext('light');
function App() {
return <Toolbar />; // no Provider!
}
function Btn() { return <b>{useContext(ThemeContext)}</b>; }Order the three steps to use Context.
Read it in any descendant: const theme = useContext(ThemeContext)
Wrap the subtree: <ThemeContext.Provider value={theme}>…</ThemeContext.Provider>const ThemeContext = createContext(defaultValue)
What does Context primarily let you avoid?
// theme needed by a deeply nested buttonYou have a user object in <App> that a deeply nested <Avatar> needs. Outline how to deliver it with Context instead of passing user through every component in between.
Try it live — edit the code and hit Run to see it rendered: