
ReactJS
Prop drilling happens when you pass data through many levels of components that don't need it, just to reach a component that does. Context lets you share data directly without passing it through every level.
Imagine you have a user logged in at the top of your app, and a component deep in the tree needs to display their name. Without Context, you'd pass the user through every component in between:
// Without Context: props drilling through every level
function App() {
const [user, setUser] = useState({ name: "Alice" });
return <Nav user={user} />;
}
function Nav({ user }) {
return <Header user={user} />;
}
function Header({ user }) {
return <UserInfo user={user} />;
}
function UserInfo({ user }) {
return <h1>Welcome, {user.name}!</h1>;
}This works, but it's cumbersome. The Nav and Header components don't care about the userβthey're just passing it along. If you have 10 levels of nesting, this becomes tedious and hard to maintain.
Context lets you skip the middle components. You create a Context, put data into it at the top level, and any component inside can access it directlyβno matter how deep.
// With Context: direct access without drilling
import { createContext, useContext, useState } from "react";
const UserContext = createContext();
function App() {
const [user, setUser] = useState({ name: "Alice" });
return (
<UserContext.Provider value={user}>
<Nav />
</UserContext.Provider>
);
}
function Nav() {
return <Header />;
}
function Header() {
return <UserInfo />;
}
function UserInfo() {
const user = useContext(UserContext);
return <h1>Welcome, {user.name}!</h1>;
}Notice: Nav and Header don't receive user as a prop. UserInfo accesses it directly from Context.
<details>
<summary>π More Examples</summary>
// Example 2: Theme context - switching between light and dark mode
import { createContext, useContext, useState } from "react";
const ThemeContext = createContext();
function App() {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={theme}>
<Page />
</ThemeContext.Provider>
);
}
function Page() {
return <Content />;
}
function Content() {
const theme = useContext(ThemeContext);
const bgColor = theme === "light" ? "white" : "black";
return <div style={{ background: bgColor }}>Content here</div>;
}</details>
Many apps need to know who's logged in throughout the entire app. Context is perfect for this:
import { createContext, useContext, useState } from "react";
const AuthContext = createContext();
function AuthProvider({ children }) {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [username, setUsername] = useState("");
const login = (name) => {
setUsername(name);
setIsLoggedIn(true);
};
const logout = () => {
setUsername("");
setIsLoggedIn(false);
};
return (
<AuthContext.Provider value={{ isLoggedIn, username, login, logout }}>
{children}
</AuthContext.Provider>
);
}
function LoginButton() {
const { isLoggedIn, login } = useContext(AuthContext);
if (isLoggedIn) {
return null;
}
return <button onClick={() => login("Alice")}>Login</button>;
}
function UserGreeting() {
const { isLoggedIn, username } = useContext(AuthContext);
return isLoggedIn ? <h1>Welcome, {username}!</h1> : <h1>Guest</h1>;
}
function App() {
return (
<AuthProvider>
<UserGreeting />
<LoginButton />
</AuthProvider>
);
}| Aspect | Prop Drilling | Context |
|---|---|---|
| Data flow | Through every level | Direct access |
| Intermediate components | Need to pass props | Unaware of data |
| Code clarity | Cumbersome with deep nesting | Clean and simple |
| Performance | Usually fine | Can be optimized |
| Best for | Direct parent-child | App-wide data |
Ready to practice? Challenges | Next: Creating Context
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep β’ Build Real β’ Verify Skills β’ Launch Forward