The useContext Hook allows React components to access shared data without passing props manually through every level of the component tree. It is useful when many components need access to the same information.
useContext is a React Hook used to read a value from a
React Context.
import { useContext } from "react";
const value = useContext(MyContext);
The Hook allows a component to access the current context value.
Context provides a way to share information with components without passing the information manually through every intermediate component.
For example, an application may have:
Suppose a value needs to travel from a top-level component to a deeply nested component.
App
↓
Header
↓
Navigation
↓
UserMenu
Passing the same prop through every level can become inconvenient. Context can provide the value directly to components that need it.
Prop drilling happens when data is passed through multiple components even though some intermediate components do not need that data themselves.
App
↓ user
Header
↓ user
Navigation
↓ user
Profile
Context can help avoid unnecessary prop passing in suitable cases.
The createContext function is used to create a context.
import { createContext } from "react";
const ThemeContext = createContext("light");
The value passed to createContext() is the default
context value.
A context can be created by importing createContext from
React.
import { createContext } from "react";
const UserContext = createContext(null);
In larger applications, contexts can be placed in separate files.
// UserContext.jsx
import { createContext } from "react";
const UserContext =
createContext(null);
export default UserContext;
This makes the context reusable across multiple components.
A provider supplies a context value to components inside it.
<ThemeContext.Provider value="dark">
<App />
</ThemeContext.Provider>
Components inside the provider can access the supplied context value.
The useContext Hook reads the nearest available context
value.
import { useContext } from "react";
function Profile() {
const theme =
useContext(ThemeContext);
return (
<h2>
Theme: {theme}
</h2>
);
}
import {
createContext,
useContext
} from "react";
const ThemeContext =
createContext("light");
function App() {
return (
<ThemeContext.Provider value="dark">
<Profile />
</ThemeContext.Provider>
);
}
function Profile() {
const theme =
useContext(ThemeContext);
return (
<h1>
Current Theme: {theme}
</h1>
);
}
export default App;
The provider's value determines the data available to
consuming components.
<UserContext.Provider
value="Rahul"
>
<Profile />
</UserContext.Provider>
The Profile component can read this value using
useContext.
const LanguageContext =
createContext("English");
<LanguageContext.Provider value="Hindi">
<App />
</LanguageContext.Provider>
The current language can then be accessed by descendant components.
const CountContext =
createContext(0);
<CountContext.Provider value={10}>
<Counter />
</CountContext.Provider>
Context values can contain numbers as well as other JavaScript values.
A context value can be an object containing multiple related values.
const UserContext =
createContext(null);
const user = {
name: "Rahul",
role: "Student"
};
<UserContext.Provider value={user}>
<Profile />
</UserContext.Provider>
function Profile() {
const user =
useContext(UserContext);
return (
<div>
<h2>
{user.name}
</h2>
<p>
Role: {user.role}
</p>
</div>
);
}
An object can contain multiple values that should be shared.
const appData = {
username: "Rahul",
theme: "dark",
language: "English"
};
<AppContext.Provider value={appData}>
<App />
</AppContext.Provider>
function Profile() {
const {
username,
theme,
language
} = useContext(AppContext);
return (
<div>
<h2>
{username}
</h2>
<p>
Theme: {theme}
</p>
<p>
Language: {language}
</p>
</div>
);
}
Functions can also be included in a context value.
const appData = {
username: "Rahul",
logout: () => {
console.log("Logout");
}
};
A child component can access and call the function through context.
Context is often combined with useState to share both a
value and a function that updates it.
const [theme, setTheme] =
useState("light");
<ThemeContext.Provider
value={{
theme,
setTheme
}}
>
<App />
</ThemeContext.Provider>
function ThemeButton() {
const {
theme,
setTheme
} = useContext(ThemeContext);
function toggleTheme() {
setTheme(
theme === "light"
? "dark"
: "light"
);
}
return (
<button onClick={toggleTheme}>
Theme: {theme}
</button>
);
}
The setter function can be shared through context when components need to update the shared state.
A custom provider component can keep context logic organized.
function ThemeProvider({ children }) {
const [theme, setTheme] =
useState("light");
return (
<ThemeContext.Provider
value={{
theme,
setTheme
}}
>
{children}
</ThemeContext.Provider>
);
}
function App() {
return (
<ThemeProvider>
<Header />
<Main />
<Footer />
</ThemeProvider>
);
}
All components inside the provider can access the context.
ThemeProvider
|
+--- Header
|
+--- Main
| |
| +--- Profile
|
+--- Footer
The Profile component can access the context even though Header or other intermediate components do not need to receive the theme as a prop.
import {
createContext,
useContext,
useState
} from "react";
const ThemeContext =
createContext();
function App() {
const [theme, setTheme] =
useState("light");
return (
<ThemeContext.Provider
value={{
theme,
setTheme
}}
>
<ThemeButton />
</ThemeContext.Provider>
);
}
function ThemeButton() {
const {
theme,
setTheme
} = useContext(ThemeContext);
function toggleTheme() {
setTheme(
theme === "light"
? "dark"
: "light"
);
}
return (
<button onClick={toggleTheme}>
Current Theme: {theme}
</button>
);
}
export default App;
Context can be useful for sharing user information across an application.
const UserContext =
createContext(null);
const user = {
name: "Rahul",
loggedIn: true
};
<UserContext.Provider value={user}>
<Dashboard />
</UserContext.Provider>
A common use case is sharing a theme across multiple components.
const ThemeContext =
createContext();
function Header() {
const { theme } =
useContext(ThemeContext);
return (
<header>
Theme: {theme}
</header>
);
}
function Footer() {
const { theme } =
useContext(ThemeContext);
return (
<footer>
Theme: {theme}
</footer>
);
}
| Props | Context |
|---|---|
| Passed explicitly from parent to child. | Can be read by descendant components. |
| Useful for direct parent-child data flow. | Useful for shared values across many components. |
| Data is visible in the component interface. | Data can be accessed through the context. |
Context is useful, but it does not need to be used for every piece of data.
For simple parent-to-child communication, normal props are often clearer.
function Parent() {
return (
<Child name="Rahul" />
);
}
function Child({ name }) {
return (
<h2>
{name}
</h2>
);
}
Use the simplest data-sharing approach that fits the component structure.
import {
createContext,
useContext,
useState
} from "react";
const UserContext =
createContext(null);
function App() {
const [user, setUser] = useState({
name: "Rahul",
role: "Student"
});
return (
<UserContext.Provider
value={{
user,
setUser
}}
>
<Profile />
</UserContext.Provider>
);
}
function Profile() {
const {
user,
setUser
} = useContext(UserContext);
function changeName() {
setUser({
...user,
name: "Amit"
});
}
return (
<div>
<h2>
Name: {user.name}
</h2>
<p>
Role: {user.role}
</p>
<button onClick={changeName}>
Change Name
</button>
</div>
);
}
export default App;
useContext to read the current context value.useState.useContext reads a value from React Context.createContext() is used to create a context.useState for shared state.
Question: What is the main purpose of the
useContext Hook in React?