Prop drilling occurs when data must be passed down through multiple intermediate child components that do not need the data themselves, solely to reach a deeply nested component.
The React Context API provides a way to share global state (such as themes, user authentication sessions, or language locales) across the entire component tree without passing props manually at every level.
flowchart TD
Provider["<ThemeContext.Provider value={{ theme, toggleTheme }}>"] --> Parent["Intermediate Component (No Prop Drilling)"]
Parent --> Child["Deeply Nested Component"]
Child --> Consume["useContext(ThemeContext)"]
import React, { createContext, useContext, useState } from 'react';
// 1. Create Context Instance
const ThemeContext = createContext(null);
// 2. Create Custom Provider Component
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme((prev) => (prev === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
<div className={`app-wrapper theme-${theme}`}>{children}</div>
</ThemeContext.Provider>
);
}
// 3. Custom Consumer Hook
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}
// 4. Consuming Component
export function HeaderNav() {
const { theme, toggleTheme } = useTheme();
return (
<header className="navbar">
<span>Current Theme: {theme}</span>
<button onClick={toggleTheme}>Toggle Theme</button>
</header>
);
}
useState is cleaner and more performant.useMemo if the value object contains complex data to prevent child re-renders on parent state updates.Create an AuthContext provider that exposes user state and login() / logout() state modifier functions.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With