useContext
Reads and subscribes to a context value. Re-renders the component whenever the nearest provider's value changes.
Signature
const value = useContext<T>(context: React.Context<T>)Parameters
| Parameter | Type | Description |
|---|---|---|
| context | React.Context<T> | The context object created by React.createContext. The hook returns the value from the nearest matching Provider above in the tree. |
Return Value
The current context value, determined by the value prop of the nearest Provider for this context above the calling component.
Examples
import { createContext, useContext, useState } from 'react';
const ThemeContext = createContext<'light' | 'dark'>('light');
function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
return (
<ThemeContext.Provider value={theme}>
{children}
<button onClick={() => setTheme(t => t === 'light' ? 'dark' : 'light')}>
Toggle
</button>
</ThemeContext.Provider>
);
}
function Card() {
const theme = useContext(ThemeContext);
return <div className={theme === 'dark' ? 'bg-black' : 'bg-white'}>Card</div>;
}import { createContext, useContext } from 'react';
interface AuthContextType {
user: { name: string; email: string } | null;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
}
const AuthContext = createContext<AuthContextType | null>(null);
function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
}
function Dashboard() {
const { user, logout } = useAuth();
return (
<div>
<p>Welcome, {user?.name}</p>
<button onClick={logout}>Log out</button>
</div>
);
}import { createContext, useContext } from 'react';
const LangContext = createContext('en');
const CurrencyContext = createContext('USD');
function PriceTag({ amount }: { amount: number }) {
const lang = useContext(LangContext);
const currency = useContext(CurrencyContext);
const formatted = new Intl.NumberFormat(lang, {
style: 'currency',
currency,
}).format(amount);
return <span>{formatted}</span>;
}
// Wrap once at the top:
// <LangContext.Provider value="de">
// <CurrencyContext.Provider value="EUR">
// <PriceTag amount={42.5} /> → "42,50 €"
// </CurrencyContext.Provider>
// </LangContext.Provider>Common Pitfalls
Using useContext without a Provider above in the tree — the hook returns the default value from createContext, which may be unexpected.
Placing frequently-changing values in context causes all consumers to re-render. Split contexts or memoize the value object.
Passing a new object literal as the Provider value on every render, causing unnecessary re-renders of all consumers.
Not creating a custom hook wrapper that throws when context is null, leading to silent bugs.
Understanding useContext
useContext provides a way to pass data through the component tree without manually threading props at every level. It is React's built-in solution to the "prop drilling" problem, where intermediate components must forward props they don't use just to pass them deeper. Combined with createContext and a Provider component, useContext forms a clean dependency injection system.
When the value of a Provider changes, every component calling useContext for that context will re-render. This behavior is by design but can become a performance concern if the context value changes frequently or if many components subscribe to it. A common optimization is to split a large context into smaller, focused contexts — one for user data, another for theme, another for locale — so that changes only affect relevant consumers.
Another important optimization is memoizing the context value. If you pass an object literal as the value prop to a Provider, a new object is created on every render, causing all consumers to re-render even when the actual data hasn't changed. Wrapping the value in useMemo solves this. For contexts that combine state with dispatch (like a reducer pattern), consider providing state and dispatch through separate contexts.
A best practice is to create a custom hook that wraps useContext and includes a null check. This provides a better developer experience by throwing a descriptive error when the hook is called outside its Provider, rather than silently returning undefined. Libraries like Zustand and Jotai offer alternative global state approaches that avoid some of context's re-rendering trade-offs.
Related Hooks
useStateDeclares a state variable that triggers re-renders when updated. The most fundamental React hook for managing component-level state.
useMemoCaches the result of an expensive computation between re-renders, recomputing only when dependencies change.
useReducerManages complex state logic with a reducer function. Preferred over useState when state transitions depend on the previous state or involve multiple sub-values.
Explore All React Hooks
Browse our complete reference of 19 React hooks with signatures, examples, pitfalls, and in-depth explanations.