docs / React
Mastering React Context API
Learn how to effectively manage global state in React applications using the Context API
3 min read
Mastering React Context API
The Context API provides a way to share values like themes, user data, or any other global state between components without explicitly passing props through every level of the component tree.
Understanding Context API
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
Creating a Context
Here's how to create a simple theme context:
// ThemeContext.js
import React, { createContext, useState } from 'react';
// Create a context with a default value
export const ThemeContext = createContext({
theme: 'light',
toggleTheme: () => {},
});
// Create a provider component
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
};
return <ThemeContext.Provider value={{ theme, toggleTheme }}>{children}</ThemeContext.Provider>;
};Using Context in Components
You can consume the context in any component:
// ThemedButton.js
import React, { useContext } from 'react';
import { ThemeContext } from './ThemeContext';
export const ThemedButton = () => {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<button
onClick={toggleTheme}
style={{
backgroundColor: theme === 'light' ? '#fff' : '#333',
color: theme === 'light' ? '#333' : '#fff',
padding: '10px 15px',
border: 'none',
borderRadius: '4px',
}}
>
Toggle Theme
</button>
);
};Wrapping Your App with Context
To make the context available throughout your app:
// App.js
import React from 'react';
import { ThemeProvider } from './ThemeContext';
import { ThemedButton } from './ThemedButton';
function App() {
return (
<ThemeProvider>
<div className="App">
<h1>Context API Example</h1>
<ThemedButton />
</div>
</ThemeProvider>
);
}
export default App;Multiple Contexts
You can use multiple contexts in your application:
// App.js
import React from 'react';
import { ThemeProvider } from './ThemeContext';
import { UserProvider } from './UserContext';
import { ThemedButton } from './ThemedButton';
import { UserProfile } from './UserProfile';
function App() {
return (
<ThemeProvider>
<UserProvider>
<div className="App">
<h1>Multiple Contexts Example</h1>
<ThemedButton />
<UserProfile />
</div>
</UserProvider>
</ThemeProvider>
);
}Context with useReducer
For more complex state management, combine Context with useReducer:
// AppContext.js
import React, { createContext, useReducer } from 'react';
// Initial state
const initialState = {
user: null,
isAuthenticated: false,
theme: 'light',
};
// Reducer function
const reducer = (state, action) => {
switch (action.type) {
case 'LOGIN':
return {
...state,
user: action.payload,
isAuthenticated: true,
};
case 'LOGOUT':
return {
...state,
user: null,
isAuthenticated: false,
};
case 'TOGGLE_THEME':
return {
...state,
theme: state.theme === 'light' ? 'dark' : 'light',
};
default:
return state;
}
};
// Create context
export const AppContext = createContext();
// Provider component
export const AppProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
return <AppContext.Provider value={{ state, dispatch }}>{children}</AppContext.Provider>;
};Performance Considerations
Context is not optimized for high-frequency updates. For those cases, consider:
- Splitting your context into smaller, more focused contexts
- Using memoization with
React.memo,useMemo, anduseCallback - Using a more specialized state management library like Redux for complex state
Best Practices
- Don't overuse context: Not everything needs to be in context. Local state is often sufficient.
- Split contexts by domain: Create separate contexts for different domains (e.g., user, theme, notifications).
- Memoize values: Use
useMemoto prevent unnecessary re-renders. - Consider composition: Sometimes component composition is cleaner than context.
By mastering the Context API, you can create more maintainable React applications with cleaner component hierarchies and more efficient state management.