useContext for Global State
Create a Context, wrap a subtree with its Provider, and consume the value with useContext to share theme or auth state without prop drilling.
useContext for Global State is a free Frontend Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Problem with Prop Drilling
Prop drilling means passing data through many intermediate components that don't use it, just to reach a deeply nested child. Context solves this by making a value available to any component in the tree without explicit passing.
Creating a Context
createContext(defaultValue) creates a Context object. The default value is used when a component reads the context without a matching Provider above it.
import { createContext } from 'react';
interface ThemeContextType {
theme: 'light' | 'dark';
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType>({
theme: 'light',
toggleTheme: () => {}
});Providing the Context
Wrap the part of the tree that needs the context with the Provider. All components inside can read the context value.
function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
const toggleTheme = () => setTheme(t => t === 'light' ? 'dark' : 'light');
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
// In app root:
<ThemeProvider>
<App />
</ThemeProvider>Consuming with useContext
Any component inside the Provider can access the context value with useContext(ThemeContext). No need to pass anything as a prop.
function ThemeToggle() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<button onClick={toggleTheme}>
Switch to {theme === 'light' ? 'dark' : 'light'} mode
</button>
);
}Custom Hook to Wrap useContext
Export a custom hook that calls useContext internally. This is cleaner than exposing the context directly and lets you add validation.
function useTheme() {
const ctx = useContext(ThemeContext);
if (!ctx) throw new Error('useTheme must be used inside ThemeProvider');
return ctx;
}
// Usage:
const { theme } = useTheme();Context Re-renders
When the Provider's value changes, all consumers re-render. If the value is an object, a new object reference each render will cause all consumers to re-render. Memoize the value with useMemo to prevent this.
const value = useMemo(
() => ({ theme, toggleTheme }),
[theme] // toggleTheme is stable if created with useCallback
);
<ThemeContext.Provider value={value}>When to Use Context
Good for: theme, locale, authenticated user, feature flags, notification system. Not ideal for: high-frequency updates (every keystroke), large complex state (use a store instead).
Multiple Contexts
You can have multiple independent contexts. Keep them focused — an AuthContext for auth, a ThemeContext for theme. Avoid a single god context that holds everything.
Context vs Redux
Context is built-in and sufficient for infrequently changing global data. Redux/Zustand/Pinia are better for complex state with many updates, time-travel debugging, or middleware needs.
Auth Context Pattern
A common pattern: an AuthContext that holds the current user and auth methods. Consuming components get user without any prop drilling.
interface AuthContext {
user: User | null;
login: (creds: Credentials) => Promise<void>;
logout: () => void;
}
const AuthCtx = createContext<AuthContext | null>(null);
export const useAuth = () => {
const ctx = useContext(AuthCtx);
if (!ctx) throw new Error('Outside AuthProvider');
return ctx;
};Context and TypeScript
Type the context with an interface. Use null as the initial value and throw in the custom hook if it's null. This prevents the impossible 'consumed outside provider' state silently.
Performance: memo + Context
Components wrapped with React.memo don't re-render unless their props change. If a context consumer's output only depends on part of the context, split the context or use selector patterns to avoid unnecessary re-renders.
Quick Check
What does useContext(MyContext) return when called inside a component that has no Provider above it?
Recap: useContext
createContext creates a context with a default value. Wrap the tree with Provider to supply a value. useContext reads the value anywhere inside. Custom hooks wrap useContext for validation. Memoize the Provider value to prevent unnecessary re-renders. Use for infrequently-changing global data like theme and auth.
Frequently asked questions
Is the “useContext for Global State” lesson free?
Yes — the full text of “useContext for Global State” is free to read here on the web, and the Frontend Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO.
What will I learn in “useContext for Global State”?
Create a Context, wrap a subtree with its Provider, and consume the value with useContext to share theme or auth state without prop drilling. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Frontend Academy?
No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “useContext for Global State” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Frontend Academy lesson?
Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- useContext for Global State
- useReducer for Complex State
- useMemo and useCallback for Performance
- Custom Hooks: Extracting Reusable Logic