
Day 14: Understanding Context API in React
So far in this series, weβve worked with React state using useState
, useReducer
, and even Custom Hooks. But thereβs still a problem you might have noticed:
When a piece of state is needed by multiple components at different levels, we end up passing props down multiple layers. This process is called prop drilling, and it can quickly become messy.
π This is where the Context API in React comes to the rescue.
What is Context API in React?
The Context API in React is a way to share data globally across components without manually passing props down the tree.
Think of it as a centralized data store that components can directly access, no matter where they are in the component hierarchy.
When to Use Context API in React?
- When multiple components need the same data (e.g., user authentication, theme, language).
- To avoid prop drilling (passing props through components that donβt even use them).
- For global state management in small to medium-sized apps.
Syntax of Context API in React
- Create Context
const MyContext = React.createContext();
- Provide Context
Wrap a parent component with aProvider
and pass the value.<MyContext.Provider value={someValue}> <ChildComponent /> </MyContext.Provider>
- Consume Context
Access the value usinguseContext
.const value = useContext(MyContext);
Example 1: Theme Context with Context API in React
Letβs build a theme switcher using the Context API in React.
import React, { createContext, useContext, useState } from "react";
// 1. Create Context
const ThemeContext = createContext();
// 2. Create Provider Component
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>
);
}
// 3. Consume Context
function ThemedComponent() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<div className={`p-4 ${theme === "light" ? "bg-white" : "bg-gray-800 text-white"}`}>
<h2 className="text-lg font-bold mb-2">Context API in React Example</h2>
<p>Current Theme: {theme}</p>
<button
onClick={toggleTheme}
className="px-3 py-2 bg-blue-500 text-white rounded mt-2"
>
Toggle Theme
</button>
</div>
);
}
// Root App
function App() {
return (
<ThemeProvider>
<ThemedComponent />
</ThemeProvider>
);
}
export default App;
β
Now, any component wrapped inside ThemeProvider
can access theme
and toggleTheme
without prop drilling.
Example 2: User Authentication Context
Imagine you have a logged-in user and need to show their info across multiple components.
import React, { createContext, useContext } from "react";
const UserContext = createContext();
function UserProvider({ children }) {
const user = { name: "Anand", role: "Developer" };
return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
}
function Navbar() {
const user = useContext(UserContext);
return <p className="p-2">Welcome, {user.name} ({user.role})</p>;
}
function Dashboard() {
const user = useContext(UserContext);
return <p className="p-2">Access granted for {user.role}</p>;
}
function App() {
return (
<UserProvider>
<Navbar />
<Dashboard />
</UserProvider>
);
}
export default App;
β
The UserProvider
supplies user data, and Navbar + Dashboard can access it directly without props. This example demonstrates how to share user authentication details (like username, email, role, etc.) across multiple components without passing props manually.
Step 1: Create Context
const UserContext = createContext();
- This creates a UserContext object.
- Think of it as a “data pipe” that can carry user information anywhere inside your app.
Step 2: Provide Context (UserProvider)
function UserProvider({ children }) {
const user = { name: "Anand", role: "Developer" };
return (
<UserContext.Provider value={user}>
{children}
</UserContext.Provider>
);
}
- The
UserProvider
component wraps other components and provides the user data. - Here,
user
is just a simple object, but in real apps it could come from:- API response (after login),
- Firebase authentication,
- JWT token, etc.
- Whatever value we pass into
value={user}
becomes available to all child components.
Step 3: Consume Context in Navbar
function Navbar() {
const user = useContext(UserContext);
return <p className="p-2">Welcome, {user.name} ({user.role})</p>;
}
- Here, instead of receiving
user
as a prop, we use:
const user = useContext(UserContext);
useContext(UserContext)
instantly gives access to theuser
object provided byUserProvider
.- This allows Navbar to display:
Welcome, Anand (Developer)
Step 4: Consume Context in Dashboard
function Dashboard() {
const user = useContext(UserContext);
return <p className="p-2">Access granted for {user.role}</p>;
}
- Same thing again β no props needed.
- Dashboard directly accesses the
user
info. - Output will be:
Access granted for Developer
Step 5: Wrap Everything in App
function App() {
return (
<UserProvider>
<Navbar />
<Dashboard />
</UserProvider>
);
}
- Both
Navbar
andDashboard
are wrapped insideUserProvider
. - This means both can directly access the user data without prop drilling.
How Output Looks
Welcome, Anand (Developer)
Access granted for Developer
Real-World Use Case
In a real app, instead of hardcoding user
, you might fetch it from an API:
function UserProvider({ children }) {
const [user, setUser] = useState(null);
useEffect(() => {
// Simulate fetching from backend
setTimeout(() => {
setUser({ name: "Anand", role: "Admin" });
}, 1000);
}, []);
return (
<UserContext.Provider value={user}>
{children}
</UserContext.Provider>
);
}
Now, any component in your app (Navbar, Dashboard, Sidebar, Footer) can access user
directly with:
const user = useContext(UserContext);
So the biggest win here is: you donβt have to pass user
as a prop from App β Navbar β SubNavbar β Menu β Button
.
You just wrap everything in UserProvider
and use useContext(UserContext)
anywhere.
Benefits of Context API in React
- Eliminates prop drilling.
- Provides global state with minimal setup.
- Works perfectly for small to medium apps.
- Pairs well with Custom Hooks for reusable contexts.
Limitations of Context API in React
- Not always suitable for very large applications (where Redux or Zustand may be better).
- Updating context can re-render all consumers, which may impact performance.
External Link
π Learn more from the React official Context API docs.
Wrapping Up
Today we learned:
- What the Context API in React is.
- How it helps avoid prop drilling.
- Built real-world examples with theme switching and user authentication.
π In the next blog (Day 15), weβll explore Handling Forms in React, covering controlled vs uncontrolled inputs and simple validation logic.