If you’re learning React, you’ll quickly run into this question:
“How do I share data between many components without passing props everywhere?”
That problem is exactly why useContext exists.
1. The Problem useContext Solves
Let’s start with the pain.
Imagine this component tree:
App
└── Layout
└── Sidebar
└── Profile
└── Avatar
Now imagine:
- The logged-in user lives in
App - Only
Avatarneeds the user’s name
Without context, you must pass props like this:
<App user={user}>
<Layout user={user}>
<Sidebar user={user}>
<Profile user={user}>
<Avatar user={user} />
</Profile>
</Sidebar>
</Layout>
</App>
This is called prop drilling.
Why prop drilling is bad
- Components receive data they don’t need
- Code becomes noisy
- Refactoring is painful
- Bugs creep in easily
2. What Is Context (Plain English)
Context is a way to store data once and read it anywhere below.
In human terms:
“Make this data global for part of the app.”
Context does not replace state.
It just changes how state is shared.
3. What Is useContext?
useContext is the hook that lets a component read data from a Context.
Think of it as:
“Give me the shared data without passing props.”
4. A Very Simple Example (No Complexity)
Step 1: Create a Context
import { createContext } from "react";
const UserContext = createContext(null);
export default UserContext;
This creates a container for shared data.
Step 2: Provide the Context (at the top)
import { useState } from "react";
import UserContext from "./UserContext";
function App() {
const [user, setUser] = useState({ name: "John" });
return (
<UserContext.Provider value={user}>
<Dashboard />
</UserContext.Provider>
);
}
What’s happening:
-
UserContext.Providerwraps your app -
value={user}is the shared data - Every component inside can access it
Step 3: Consume the Context
import { useContext } from "react";
import UserContext from "./UserContext";
function Dashboard() {
const user = useContext(UserContext);
return <h1>Hello {user.name}</h1>;
}
No props.
No drilling.
Just access.
5. Backend Mental Model (Very Important)
Think of Context like:
| Backend Concept | React Context |
|---|---|
| Config file | Context |
| Auth middleware | Provider |
| Request access | useContext |
Once data is in Context:
- You don’t pass it manually
- You just read it when needed
6. When Should You Use useContext?
Good use cases
- Logged-in user
- Theme (dark/light)
- Language
- App-wide settings
Bad use cases
- Highly dynamic data (typing, counters)
- Large, frequently changing lists
- Complex business logic
7. Sharing State AND Actions (Common Pattern)
Usually, you’ll share both:
- Data
- Functions to update the data
<UserContext.Provider value={{ user, setUser }}>
<App />
</UserContext.Provider>
Then consume:
const { user, setUser } = useContext(UserContext);
This is how login/logout works.
8. Why Context Is NOT a State Manager
Important beginner truth:
Context does not manage state.
It only distributes state.
You still need:
useStateuseReducer- or another store
Context is the delivery system, not the engine.
9. Common Beginner Mistakes
❌ Using Context for everything
This leads to:
- Performance issues
- Hard-to-track updates
❌ Putting too much logic in Context
Keep it simple:
- Data
- Small helpers
❌ Forgetting Provider
If there’s no Provider, useContext returns undefined.
10. useContext vs Props (Quick Comparison)
| Props | useContext |
|---|---|
| Explicit | Implicit |
| Best for local data | Best for shared data |
| Easy to trace | Can be hidden |
| No setup | Needs Provider |
11. A Simple Rule to Remember
If many components need the same data, and passing props feels annoying — use Context.
12. Where useContext Fits in Your Learning Path
You should learn useContext after:
useState- Passing props
- Lifting state up
And before:
- Redux
- Zustand
Final Summary
-
useContextsolves prop drilling - It lets components read shared data
- It works best for global, stable data
- It does not replace state management libraries
Once this clicks, React starts feeling clean and intentional, not messy.
Top comments (0)