React Context API
In large React applications, passing data through multiple component levels (known as prop drilling) can become messy and difficult to maintain.
To solve this, React provides a built-in feature called the Context API — a powerful tool for managing global state and sharing data across components without having to manually pass props at every level.
What is the React Context API?
The Context API allows you to create global variables or data that can be accessed by any component in your app — no matter how deeply nested it is in the component tree.
You can think of it as a “shared data store” within React, where components can both provide and consume values.
Key Concepts:
| Concept | Description |
|---|---|
| Context | A global object created using React.createContext() |
| Provider | A component that supplies data to the component tree |
| Consumer | Any component that uses the data from the Provider |
| useContext Hook | A simpler way to access context values without wrapping components in a Consumer |
Syntax:
const MyContext = React.createContext(defaultValue);
This creates a new Context object.
You’ll then use the Provider and Consumer components to share and access the data.
Creating and Providing Context
The Provider component wraps parts of your app and passes down values through the value prop.
import React, { createContext, useState } from "react";
const UserContext = createContext(); // Create context
function App() {
const [user, setUser] = useState("Alice");
return (
<UserContext.Provider value={{ user, setUser }}>
<Toolbar />
</UserContext.Provider>
);
}
function Toolbar() {
return (
<div>
<UserProfile />
</div>
);
}
Consuming Context Data
There are two ways to consume context data:
A. Using useContext (Recommended)
import React, { useContext } from "react";
import { UserContext } from "./App";
function UserProfile() {
const { user, setUser } = useContext(UserContext);
return (
<div>
<h2>Logged in as: {user}</h2>
<button onClick={() => setUser("Bob")}>Switch User</button>
</div>
);
}
Benefits of useContext:
- Cleaner and easier than the traditional Consumer pattern
- No nested render functions
- Updates automatically when context value changes
B. Using Context.Consumer (Older Pattern)
Before hooks, React used the Consumer pattern to access context data.
<UserContext.Consumer>
{({ user, setUser }) => (
<div>
<h2>Welcome, {user}!</h2>
<button onClick={() => setUser("Charlie")}>Change User</button>
</div>
)}
</UserContext.Consumer>
Updating Global State with Context
Context isn’t just for static values — you can store and update dynamic state as well.
By combining useState (or even useReducer) with Context, you can create global state managers.
Example:
import React, { createContext, useContext, useState } from "react";
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
const toggleTheme = () => {
setTheme((prev) => (prev === "light" ? "dark" : "light"));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function ThemeButton() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<buttononClick={toggleTheme}
style={{
background: theme === "dark" ? "#333" : "#fff",
color: theme === "dark" ? "#fff" : "#000",
}}
>
Toggle Theme (Current: {theme})
</button>
);
}
Usage:
function App() {
return (
<ThemeProvider>
<ThemeButton />
</ThemeProvider>
);
}
Real-World Use Cases
The Context API is commonly used for:
- Theme Management (light/dark mode)
- User Authentication (login, logout, user details)
- Language/Localization
- Global Settings or Configurations
- Shopping Cart or App-wide Data
Benefits of Using Context API
- Eliminates Prop Drilling – No need to manually pass props through every component.
- Simplifies Global State – Manage shared data easily.
- Improves Readability – Clean, declarative structure.
- Works with Hooks – Combine with
useState,useReducer, or custom hooks. - Lightweight Alternative to Redux – Ideal for small to medium apps.
