React Context API
In this article, we will learn about the React Context API and how it can be used to manage global state in a React application.
What is the React Context API?
The React Context API is a way to pass data through the component tree without having to pass props down manually at every level. It allows you to share data between components without having to explicitly pass it through the props of each component.
The Context API consists of two main components:
- Provider: The
Provider
component is used to provide the data to the components that need it. It accepts avalue
prop that contains the data to be shared. - Consumer: The
Consumer
component is used to consume the data provided by theProvider
. It uses a render prop pattern to access the shared data.
Basic structure of Context API
There are 3 basic steps to use the Context API
- Create a new context object
- Create a provider component
- Consume the context using a consumer component
Example:
- Create a new context object
// Create a context
const MyContext = React.createContext();
- Create a provider component
// Create a provider
function MyProvider({ children }) {
const [state, setState] = React.useState(initialState);
return (
<MyContext.Provider value={{ state, setState }}>
{children}
</MyContext.Provider>
);
}
- Consume the context
function MyComponent() {
return (
<MyContext.Consumer>
{({ state, setState }) => (
<div>
<p>State: {state}</p>
<button onClick={() => setState(newState)}>Update State</button>
</div>
)}
</MyContext.Consumer>
);
}
Example: Theme toogle using Context API
src/
├── context/
│ └── ThemeContext.js # Context creation and custom hook
├── providers/
│ └── ThemeProvider.js # Provider component with state management
├── components/
│ └── ThemedComponents.js # Components that consume the context
└── App.js # Main application component
- ThemeContext.js
import { createContext, useContext } from 'react';
// Create the context
export const ThemeContext = createContext();
// Custom hook to use the theme context
export const useTheme = () => {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
};
- ThemeProvider.js
import React, { useState } from 'react';
import { ThemeContext } from '../context/ThemeContext';
export const ThemeProvider = ({ children }) => {
const [isDark, setIsDark] = useState(false);
const toggleTheme = () => {
setIsDark(prev => !prev);
};
// The value object contains our state and functions
const value = {
isDark,
toggleTheme
};
return (
<ThemeContext.Provider value={value}>
{children}
</ThemeContext.Provider>
);
};
- ThemedButton.js
import React from 'react';
import { Sun, Moon } from 'lucide-react';
import { useTheme } from '../context/ThemeContext';
export const ThemedButton = () => {
const { isDark, toggleTheme } = useTheme();
return (
<button
onClick={toggleTheme}
className={`p-4 rounded-lg flex items-center gap-2 ${
isDark
? 'bg-gray-800 text-white'
: 'bg-blue-100 text-gray-800'
}`}
>
{isDark ? <Moon size={20} /> : <Sun size={20} />}
Toggle {isDark ? 'Light' : 'Dark'} Mode
</button>
);
};
- App.js
import React from 'react';
import { ThemeProvider } from './providers/ThemeProvider';
import { ThemedButton } from './components/ThemedButton';
const App = () => {
return (
<ThemeProvider>
<div className="p-8">
<h1 className="text-2xl font-bold mb-4">
Theme Context Example
</h1>
<ThemedButton />
</div>
</ThemeProvider>
);
};
export default App;