useContext — Skipping the Middlemen
The reading list gets a dark theme. App holds the current theme, but the buttons that need it sit four components down. Passing theme through every layer — each one receiving it only to hand it on — is called prop drilling, and it makes every middle component care about data it never uses. Context lets a value skip the middlemen.
The rule
Provide it high, read it low, fall back to the default.
Three pieces, usually in three places:
// ThemeContext.js — create it, with a default
import { createContext } from 'react';
export const ThemeContext = createContext('light');// App.jsx — provide it high
function App() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={theme}>
<ReadingList />
</ThemeContext.Provider>
);
}// LikeButton.jsx — read it low
import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';
function LikeButton() {
const theme = useContext(ThemeContext);
return <button className={`like like-${theme}`}>♥</button>;
}In React 19 you can write <ThemeContext value={theme}> directly; .Provider still works and is what most existing code uses.
Provide it high. Everything inside the provider, at any depth, can read the value.
Read it low. useContext(ThemeContext) returns the value from the nearest provider above the component. When that value changes, every component reading it re-renders. Providers can nest: an inner provider overrides the outer one for its own subtree.
Fall back to the default. With no provider above it, useContext returns the default passed to createContext.
Context often carries state: put [theme, setTheme] or a dispatch from useReducer into the value, and any component below can both read and change it.
The shortcut
Ask: "How many components between the owner and the reader don't care about this value?" None or one → pass props. Several, or many scattered readers → context.
Start at the reader
LikeButtoncallsuseContext(ThemeContext).
Context is not a replacement for every prop. It hides where data comes from, so keep it for things many parts of the app need: theme, signed-in user, language.
Drills
Answer fast — trust the rule.
What does useContext(ThemeContext) return when there is no provider above the component?
Two providers are nested: outer value="dark", inner value="light". A button inside both reads the theme. What does it get?
Which problem does context mainly solve?
A value is needed by one child directly below its owner. What is the simplest choice?
Remember
- Provide it high, read it low, fall back to the default.
- Several uninterested middlemen or many scattered readers → context; otherwise props.
- Trap: using context for everything, which hides where data comes from.
