The Context API is a React feature that allows data to be shared between components without passing props manually through every level of the component tree.
React Context provides a way to share values with components without explicitly passing props through every intermediate component.
Provider
↓
Parent
↓
Child
↓
Grandchild
↓
Consumer
Context can help when the same information is required by many components at different levels of the component tree.
Common examples include:
Suppose data needs to move from a parent to a deeply nested component. Without Context, the data may need to be passed through components that do not actually use it.
App
↓
Layout
↓
Dashboard
↓
Sidebar
↓
Profile
This repeated passing of props is often called prop drilling.
Prop drilling occurs when data is passed through several components only so that a deeply nested component can receive it.
<App user={user}>
↓
<Layout user={user}>
↓
<Dashboard user={user}>
↓
<Profile user={user}>
The createContext() function creates a Context object.
import {
createContext
} from "react";
const UserContext =
createContext(null);
The context can then be provided to components.
A context is normally created in a separate file.
import {
createContext
} from "react";
const UserContext =
createContext();
export default UserContext;
For example, the file can be named UserContext.jsx.
A Provider makes a context value available to components below it in the tree.
<UserContext.Provider
value={user}
>
<Dashboard />
</UserContext.Provider>
The value prop contains the data that should be shared.
const user = {
name: "Rahul",
course: "React"
};
<UserContext.Provider
value={user}
>
<Profile />
</UserContext.Provider>
The useContext() Hook allows a component to read the current
context value.
import {
useContext
} from "react";
const user =
useContext(UserContext);
Once the context value is available, its properties can be used normally.
function Profile() {
const user =
useContext(UserContext);
return (
<h2>
{user.name}
</h2>
);
}
A context can provide a simple string value.
const ThemeContext =
createContext("light");
<ThemeContext.Provider
value="dark"
>
<App />
</ThemeContext.Provider>
Context can also provide numeric values.
const CountContext =
createContext(0);
<CountContext.Provider
value={10}
>
<Counter />
</CountContext.Provider>
Objects are commonly used when several related values need to be shared.
const user = {
name: "Amit",
email: "amit@example.com",
course: "React"
};
<UserContext.Provider
value={user}
>
<Profile />
</UserContext.Provider>
A context value can contain functions as well as data.
const contextValue = {
user: user,
logout: logout
};
<UserContext.Provider
value={contextValue}
>
<Dashboard />
</UserContext.Provider>
Context can be combined with useState when shared data needs to
change.
const [theme, setTheme] =
useState("light");
<ThemeContext.Provider
value={{
theme,
setTheme
}}
>
<App />
</ThemeContext.Provider>
function ThemeButton() {
const {
theme,
setTheme
} = useContext(
ThemeContext
);
return (
<button
onClick={() =>
setTheme(
theme === "light"
? "dark"
: "light"
)
}
>
Change Theme
</button>
);
}
A custom Provider component can keep context logic organized.
function UserProvider({
children
}) {
const [user, setUser] =
useState(null);
return (
<UserContext.Provider
value={{
user,
setUser
}}
>
{children}
</UserContext.Provider>
);
}
The Provider can wrap the part of the application that needs access to the context.
function App() {
return (
<UserProvider>
<Header />
<Dashboard />
<Footer />
</UserProvider>
);
}
A theme context can share the current theme with many components.
const ThemeContext =
createContext();
function App() {
const [theme, setTheme] =
useState("light");
return (
<ThemeContext.Provider
value={{
theme,
setTheme
}}
>
<Header />
<Content />
</ThemeContext.Provider>
);
}
User information can be shared through Context.
const UserContext =
createContext();
function Profile() {
const {
user
} = useContext(
UserContext
);
return (
<div>
<h2>
{user.name}
</h2>
<p>
{user.email}
</p>
</div>
);
}
| Props | Context |
|---|---|
| Passed explicitly from parent to child | Shared through a Provider |
| Good for direct component communication | Useful for values needed by many components |
| Data flow is explicit | Components can read shared context directly |
| Useful for component-specific data | Useful for application-wide or shared data |
Context is not a replacement for every use of props.
For simple parent-child communication, props are often clear and easy to understand.
<Student
name="Rahul"
course="React"
/>
Context is more useful when the same information is needed across many levels of the component tree.
Context can be useful for shared values such as:
Context does not need to be used for every piece of state.
If data is only needed by a parent and its direct child, normal props may be simpler.
<Profile
name={name}
/>
Avoid creating global context for data that has a small and local scope.
An application can have multiple contexts.
<ThemeProvider>
<UserProvider>
<App />
</UserProvider>
</ThemeProvider>
Each context can manage a different type of shared data.
useContext() with the wrong Context object.createContext()
↓
Provider
↓
value
↓
Component Tree
↓
useContext()
↓
Shared Data
import {
createContext,
useContext,
useState
} from "react";
const ThemeContext =
createContext();
function ThemeProvider({
children
}) {
const [theme, setTheme] =
useState("light");
function toggleTheme() {
setTheme(
theme === "light"
? "dark"
: "light"
);
}
return (
<ThemeContext.Provider
value={{
theme,
toggleTheme
}}
>
{children}
</ThemeContext.Provider>
);
}
function ThemeButton() {
const {
theme,
toggleTheme
} = useContext(
ThemeContext
);
return (
<div>
<p>
Current Theme:
{theme}
</p>
<button
onClick={toggleTheme}
>
Toggle Theme
</button>
</div>
);
}
function App() {
return (
<ThemeProvider>
<ThemeButton />
</ThemeProvider>
);
}
export default App;
import {
createContext,
useContext,
useState
} from "react";
const UserContext =
createContext();
function UserProvider({
children
}) {
const [user, setUser] =
useState({
name: "Rahul",
course: "React"
});
return (
<UserContext.Provider
value={{
user,
setUser
}}
>
{children}
</UserContext.Provider>
);
}
function Profile() {
const {
user
} = useContext(
UserContext
);
return (
<div>
<h2>
{user.name}
</h2>
<p>
Course:
{user.course}
</p>
</div>
);
}
function App() {
return (
<UserProvider>
<Profile />
</UserProvider>
);
}
export default App;
useContext() to read context values in functional components.Context
↓
Provider
↓
Shared Value
↓
useContext()
↓
Component
createContext() creates a Context object.value prop contains the shared data.useContext() reads the current context value.useState for shared changing data.Question: Which Hook is used to read a value from React Context?