React useContext for Theming — Dark Mode and Theme Switching
Implement theme switching with React useContext. Complete guide to creating a ThemeProvider, consuming context, and avoiding unnecessary re-renders in themed applications.
Detailed Explanation
Building a Theme System with useContext
useContext reads a value from a React context, enabling components to share data without prop drilling. Theming is one of its most iconic use cases.
Creating the Theme Context
import { createContext, useContext, useState } from "react";
type Theme = "light" | "dark";
interface ThemeContextValue {
theme: Theme;
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextValue | null>(null);
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<Theme>("dark");
const toggleTheme = () => {
setTheme(prev => prev === "dark" ? "light" : "dark");
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
Creating a Custom Hook
Wrapping useContext in a custom hook improves DX and provides runtime validation:
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error("useTheme must be used within a ThemeProvider");
}
return context;
}
Consuming the Theme
function Header() {
const { theme, toggleTheme } = useTheme();
return (
<header className={theme === "dark" ? "bg-black" : "bg-white"}>
<button onClick={toggleTheme}>
Switch to {theme === "dark" ? "light" : "dark"}
</button>
</header>
);
}
Performance Optimization
Every consumer re-renders when the context value changes. To optimize:
- Memoize the value object with useMemo to prevent new references on every render
- Split contexts by update frequency (e.g., separate ThemeContext from UserContext)
- Use React.memo on child components that do not consume context directly
Use Case
Use useContext for theming, authentication, locale, feature flags, and any data that many components at different nesting levels need to access without explicit prop passing.
Try It — React Hooks Reference
Related Topics
React useState Hook — Complete Guide with Examples
State Hooks
React useMemo — Caching Expensive Computations and Stable References
Performance Hooks
React useReducer for Complex State — Forms, State Machines, and Redux Patterns
State Hooks
React use() Hook — Reading Promises and Context Conditionally
Context Hooks