Chapter 3: Context API Advanced Usage
Chapter 3 of 15
Chapter 3: Context API Advanced Usage
3.1 Multiple Contexts
Large applications often need multiple contexts for different concerns. Properly organizing and using multiple contexts prevents prop drilling.
// Theme Context
const ThemeContext = React.createContext('light');
// User Context
const UserContext = React.createContext(null);
// Auth Context
const AuthContext = React.createContext({ isAuthenticated: false });
// Using multiple contexts
function App() {
return (
<ThemeContext.Provider value="dark">
<UserContext.Provider value={{ name: 'John' }}>
<AuthContext.Provider value={{ isAuthenticated: true }}>
<MyComponent />
</AuthContext.Provider>
</UserContext.Provider>
</ThemeContext.Provider>
);
}
function MyComponent() {
const theme = useContext(ThemeContext);
const user = useContext(UserContext);
const auth = useContext(AuthContext);
return <div className={theme}>Welcome {user.name}</div>;
}
3.2 Context Composition
// Combine multiple contexts
function AppProviders({ children }) {
return (
<ThemeProvider>
<UserProvider>
<AuthProvider>
{children}
</AuthProvider>
</UserProvider>
</ThemeProvider>
);
}
3.3 Custom Context Hooks
// Create custom hook for context
function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within ThemeProvider');
}
return context;
}
// Usage
function Component() {
const theme = useTheme(); // Cleaner API
return <div className={theme}>Content</div>;
}
3.4 Context Performance Optimization
// Split contexts to prevent unnecessary re-renders
const UserStateContext = React.createContext();
const UserDispatchContext = React.createContext();
function UserProvider({ children }) {
const [state, dispatch] = useReducer(userReducer, initialState);
return (
<UserStateContext.Provider value={state}>
<UserDispatchContext.Provider value={dispatch}>
{children}
</UserDispatchContext.Provider>
</UserStateContext.Provider>
);
}
// Components only re-render when needed
function UserName() {
const state = useContext(UserStateContext); // Only re-renders on state change
return <div>{state.name}</div>;
}