Creating Context
import { createContext, useContext, useState } from 'react';
const ThemeContext = createContext('light');
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => setTheme(p => p === 'light' ? 'dark' : 'light');
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
function ThemedButton() {
const { theme, toggleTheme } = useContext(ThemeContext);
return <button onClick={toggleTheme}>Theme: {theme}</button>;
}
Custom Hook for Context
const AuthContext = createContext(null);
function useAuth() {
const context = useContext(AuthContext);
if (!context) throw new Error('useAuth must be used within AuthProvider');
return context;
}
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = async (credentials) => {
const user = await loginAPI(credentials);
setUser(user);
};
const logout = () => setUser(null);
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
}
Context with useReducer
function cartReducer(state, action) {
switch (action.type) {
case 'ADD_ITEM':
return { ...state, items: [...state.items, { ...action.item, qty: 1 }] };
case 'REMOVE_ITEM':
return { ...state, items: state.items.filter(i => i.id !== action.id) };
default:
return state;
}
}
function CartProvider({ children }) {
const [state, dispatch] = useReducer(cartReducer, { items: [] });
return (
<CartContext.Provider value={{ items: state.items, dispatch }}>
{children}
</CartContext.Provider>
);
}
Best Practices
- Split large contexts into smaller, focused ones
- Use
useMemo for context values to avoid unnecessary re-renders
- Don't put rapidly changing values in context
- Custom hooks make consuming context cleaner
Ready to Level Up Your Coding Skills?
Join Coderz Club and learn to code with challenges, battles, and an AI mentor.
Join Coderz Club Free →