Part 20: useContext Hook: Global Data Without Prop Drilling
Prop drilling occurs when you need to pass data through multiple layers of intermediate components that don't need the data themselves, just to reach a deeply nested child.
1. The Context Solution
React's Context API provides a way to share values (like authentication state, theme, or localization) across the entire component tree without explicitly passing props through every level.
[ ThemeContext.Provider value="dark" ]
│
[ App Component ]
│
[ DashboardPage ]
│
[ SettingsCard ]
│
[ DarkModeToggle (Consumes ThemeContext) ]
2. Creating and Providing Context
Step 1: Create Context and Provider (ThemeContext.jsx):
import { createContext, useState, useContext } from 'react';
const ThemeContext = createContext();
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={theme === 'dark' ? 'bg-gray-900 text-white min-h-screen' : 'bg-white text-black min-h-screen'}>
{children}
</div>
</ThemeContext.Provider>
);
}
// Custom hook for convenient consumption:
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}
Step 2: Wrap Root Component:
import { ThemeProvider } from './ThemeContext';
import MainDashboard from './MainDashboard';
export default function App() {
return (
<ThemeProvider>
<MainDashboard />
</ThemeProvider>
);
}
Step 3: Consume Deep in the Tree:
import { useTheme } from './ThemeContext';
export default function ThemeToggleBtn() {
const { theme, toggleTheme } = useTheme();
return (
<button onClick={toggleTheme} className="btn-toggle">
Active Theme: {theme.toUpperCase()} (Click to toggle)
</button>
);
}
Key Takeaways
- Use Context to avoid prop drilling for widely consumed data (auth, themes, translations).
- Create custom hooks (
useTheme()) to encapsulate context consumption safely. - Keep contexts focused on specific domains to avoid unnecessary re-renders.
In Part 21, we explore complex state machines with the useReducer Hook!

