useContext reads the nearest value from a React Context Provider above in the tree. It shares data — theme, locale, auth — without passing props through every intermediate component.
Context Provider and Consumer
Create context with createContext(defaultValue), wrap subtrees in <MyContext.Provider value={...}>, and read with useContext(MyContext) in any descendant.
When the provider's value changes, all consuming components re-render. Memoize value objects to avoid unnecessary updates.
Any component under the provider can access theme without prop drilling.
Context API Steps
const Ctx = createContext(defaultValue);
<Ctx.Provider value={currentValue}>...</Ctx.Provider>
const value = useContext(Ctx);
Default value used only when no provider exists above.
Provider value prop triggers re-renders in consumers when reference changes.
Split contexts by update frequency (theme vs user).
Custom hooks like useTheme() wrap useContext for ergonomics.
Context Quick Reference
Context API building blocks.
API
Role
createContext
Create context object
.Provider
Supply value to subtree
useContext
Read value in descendant
Custom hook
useAuth() wraps context access
Split contexts
Avoid one giant re-rendering context
vs Redux/Zustand
Context for low-frequency global data
Context Performance
A single provider with a large value object that changes often re-renders all consumers. Split into ThemeContext and AuthContext, or use selectors with Zustand for granular subscriptions.
Custom Context Hook Pattern
Export a provider component and useTheme hook from one module. Throw if hook used outside provider for clear errors.
function useTheme() {
const ctx = useContext(ThemeContext);
if (!ctx) throw new Error('useTheme must be used within ThemeProvider');
return ctx;
}
Common Mistakes
Putting fast-changing data in wide-reaching context.
Creating new object literals in Provider value every render.
Using context as a full replacement for Redux without considering perf.
Default context value masking missing provider bugs.
Key Takeaways
Context shares data across the tree without prop drilling.
useContext reads the nearest provider value.
Memoize provider values to limit re-renders.
Split contexts or use Zustand for frequently changing global state.
Pro Tip
If only two components share state, lift state up instead of reaching for context.
You understand context and useContext. Next, generate stable IDs with useId for accessibility.