In short
Passing the same prop through five components that don't even use it gets tiring fast. Context lets any component deep in the tree read a value directly.
React's built-in way to pass data deeply through the component tree without manually threading props through every intermediate component ('prop drilling').

Think of it like this
The society notice board
Instead of knocking on every flat to share the water timing, the secretary pins it on the notice board. Whoever needs it reads it. Context is that board: a provider pins a value, and any component below it can read it.
Watch it happen
Skipping the middle layers
1/5App keeps theme in state and wraps the tree in ThemeContext with value "dark".
The big ideas
What you need to know
createContext makes the board
createContext(defaultValue) creates a context. The default is used only when there's no provider above.
A provider shares the value
Wrap part of the tree with it. In React 19 you can render <ThemeContext value={...}> directly.
useContext reads it
Any component below calls useContext(ThemeContext) and gets the nearest provider's value.
A change means a re-render
When the value changes, every component reading that context re-renders. Keep each context focused on one thing.
See it in code
Walk through the code
1import { createContext, useContext, useState } from "react";2type Theme = "light" | "dark";3const ThemeContext = createContext<Theme>("light");4function SaveButton() {5 const theme = useContext(ThemeContext);6 return <button className={theme}>Save</button>;7}8export default function App() {9 const [theme, setTheme] = useState<Theme>("dark");10 return (11 <ThemeContext value={theme}>12 <SaveButton />13 <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>Toggle</button>14 </ThemeContext>15 );16}1/4createContext makes the context, with "light" as the fallback default.
SaveButton never receives a prop, yet it knows the theme. Click Toggle and it re-renders with the new value. On React 18, write ThemeContext.Provider instead.
Save yourself the pain
Common mistakes
Oops
Putting the whole app's data into one giant context.
Do this instead
Split it into ThemeContext, AuthContext and CartContext, so a cart change doesn't re-render components that only care about the theme.
Oops
Calling useContext in a component that sits outside the provider.
Do this instead
It silently gets the default value. Make sure the provider wraps every component that reads it.
Your mission
Kill some prop drilling
Quick check
A component calls useContext(ThemeContext), but there's no provider above it. What does it get?
Go deeper
- 1Build a simple theme (light/dark) context and consume it in a nested component.
- 2Learn that context updates re-render every consumer — use it thoughtfully.
- 3Compare Context to prop drilling and to full state-management libraries.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.