JAVASCRIPT
Global Theme Management with useContext and Custom Hook
Implement a global theme switcher in React using `createContext` and `useContext`. This snippet shows how to create a custom `useTheme` hook for easy theme access and toggling across components.
import React, { createContext, useContext, useState, useMemo } from 'react';
// 1. Create a Context
const ThemeContext = createContext(null);
// 2. Create a Provider Component
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
};
const themeValue = useMemo(() => ({ theme, toggleTheme }), [theme]);
return (
<ThemeContext.Provider value={themeValue}>
{children}
</ThemeContext.Provider>
);
}
// 3. Create a Custom Hook to Consume the Context
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}
// 4. Example Usage in Components
function ThemeToggle() {
const { theme, toggleTheme } = useTheme();
return (
<button onClick={toggleTheme} style={{ margin: '10px' }}>
Switch to {theme === 'light' ? 'Dark' : 'Light'} Mode
</button>
);
}
function ThemedContent() {
const { theme } = useTheme();
const style = {
backgroundColor: theme === 'light' ? '#fff' : '#333',
color: theme === 'light' ? '#333' : '#fff',
padding: '20px',
border: '1px solid #ccc',
};
return (
<div style={style}>
<p>This content respects the '{theme}' theme.</p>
</div>
);
}
function App() {
return (
<ThemeProvider>
<h1>Global Theme Example</h1>
<ThemeToggle />
<ThemedContent />
</ThemeProvider>
);
}
export default App;
How it works: This snippet demonstrates how to implement global theme management using React's Context API and a custom hook. `ThemeContext` is created to hold theme-related state and functions. `ThemeProvider` wraps the application, providing the `theme` state and a `toggleTheme` function to all its descendants. The custom `useTheme` hook simplifies consuming this context, allowing any component within the `ThemeProvider` to easily access the current theme and the function to change it, promoting reusability and clean code.