useContext
Share values across the component tree without prop drilling
Overview
Context provides a way to pass data through the tree without manually threading props. Create a context, wrap a subtree with a Provider, and consume values with useContext in any descendant.
Syntax / Usage
import { createContext, useContext, useState } from 'react'
const ThemeContext = createContext('light')
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light')
const value = { theme, setTheme }
return (
<ThemeContext.Provider value={value}>
{children}
</ThemeContext.Provider>
)
}
function useTheme() {
const ctx = useContext(ThemeContext)
if (!ctx) throw new Error('useTheme must be inside ThemeProvider')
return ctx
}
function Header() {
const { theme, setTheme } = useTheme()
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle {theme}
</button>
)
}
Examples
Auth context for current user:
const AuthContext = createContext(null)
function AuthProvider({ children }) {
const [user, setUser] = useState(null)
const login = async (email, password) => {
const u = await api.login(email, password)
setUser(u)
}
const logout = () => setUser(null)
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
)
}
Locale for i18n:
const LocaleContext = createContext('en')
// Provider at app root; consumers read locale for formatting
Common Mistakes
- Putting frequently changing values in context—every consumer re-renders
- Creating new object literals in Provider
valueeach render—memoize the value - Using context for all state instead of local state or dedicated libraries
- Forgetting a custom hook with null checks for safer consumption
See Also
use-state props components conditional-rendering