Context API
Sharing data across many components without passing props through every level - createContext, Provider, and useContext explained.
What it is, in plain English: Context lets a component tree share data without passing it down manually through every intermediate component (avoiding 'props drilling'). You create a Context with createContext(), wrap part of the tree in a Provider that supplies a value, and any descendant component can read that value with useContext() -- no matter how deeply nested. Context is best for data that many components need: theme, current user, language, or app-wide settings.
Avoiding props drilling
If many components need the same piece of data -- the current theme, the logged-in user, the selected language -- passing it down as a prop through every layer ("props drilling") gets tedious and brittle. Context lets distant descendants read a value directly, skipping all the layers in between.
The three steps
// STEP 1: Create the context (usually in its own file)
const ThemeContext = React.createContext("light"); // "light" = default value
// STEP 2: Wrap part of your tree in a Provider, supplying the actual value
function App() {
return (
<ThemeContext.Provider value="dark">
<Page />
</ThemeContext.Provider>
);
}
// STEP 3: Read the value anywhere inside, with useContext
function DeeplyNestedButton() {
const theme = React.useContext(ThemeContext);
return <button className={theme}>Click</button>;
}
// DeeplyNestedButton can be 10 levels deep -- it still reads "dark" directly,
// with NO props passed through any of the components in between.Context with state -- the common real pattern
function App() {
const [theme, setTheme] = React.useState("light");
return (
<ThemeContext.Provider value={theme}>
<button onClick={() => setTheme("dark")}>Switch to dark</button>
<Dashboard />
</ThemeContext.Provider>
);
}
// When theme state changes, EVERY component reading ThemeContext re-renders
// automatically with the new value -- no manual prop updates needed anywhere.Without Context vs with Context
// ✗ WITHOUT Context -- props drilling through layers that don't use the data:
function App() { return <Layout user={user} />; }
function Layout({ user }) { return <Sidebar user={user} />; }
function Sidebar({ user }) { return <UserMenu user={user} />; }
function UserMenu({ user }) { return <p>{user.name}</p>; }
// ✓ WITH Context -- only the component that needs it touches it:
const UserContext = React.createContext(null);
function App() { return <UserContext.Provider value={user}><Layout /></UserContext.Provider>; }
function Layout() { return <Sidebar />; } // no 'user' prop needed
function Sidebar() { return <UserMenu />; } // no 'user' prop needed
function UserMenu() {
const user = React.useContext(UserContext); // reads directly
return <p>{user.name}</p>;
}
Try It Yourself (JSX)
Official Sources
- React Documentation — Passing Data Deeply with Context
- React Documentation — useContext Reference
- React Documentation — Scaling Up with Reducer and Context
The Codex links only to official documentation. No third-party tutorials.