How to Create and Provide Context in React (Step-by-Step Guide 2025)
In React, Context provides a way to share data across multiple components without passing props manually at every level.
It is ideal for global data like:
Theme (Light/Dark mode)
Logged-in User details
Language settings
Application-wide configurations
To use Context effectively, you must create it and provide it to your component tree.
Step 1: Create Context
Use the createContext() function from React to create a new context object.
import React, { createContext } from "react"; // Step 1: Create Context export const ThemeContext = createContext(); Here:
createContext()returns a Context object.This object contains two main components:
Provider: Used to provide data
Consumer: Used to consume data
Step 2: Provide Context
To make the context data available to your app, wrap the relevant component tree with the Provider component.
import React, { useState } from "react";
import { ThemeContext } from "./ThemeContext";
import Dashboard from "./Dashboard";
function App() {
const [theme, setTheme] = useState("light");
return (
// Step 2: Provide Context
<ThemeContext.Provider value={{ theme, setTheme }}>
<div>
<h1>Welcome to Theme App</h1>
<Dashboard />
</div>
</ThemeContext.Provider>
);
}
export default App;
Explanation:
ThemeContext.Providerwraps your components.The
valueprop defines what data will be available to consumers.Any component inside
Providercan now accessthemeandsetTheme.
Understanding the Provider Flow
Think of the Provider as a data broadcaster:
The
Providersends data (value) down the tree.Any child component listening to that context can access and use it.
Visualization:
App
├── ThemeContext.Provider (value={{ theme, setTheme }})
├── Navbar
├── Dashboard
├── Sidebar
└── Settings
All of these components can read and modify theme without prop drilling.
Example: Theme Context Provider
// ThemeContext.js
import { createContext } from "react";
export const ThemeContext = createContext();// ThemeProvider.js
import React, { useState } from "react";
import { ThemeContext } from "./ThemeContext";
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
// App.js
import React from "react";
import { ThemeProvider } from "./ThemeProvider";
import HomePage from "./HomePage";
function App() {
return (
<ThemeProvider>
<HomePage />
</ThemeProvider>
);
}
export default App;
// HomePage.js
import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
function HomePage() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<div
style={{
backgroundColor: theme === "light" ? "#fff" : "#333",
color: theme === "light" ? "#000" : "#fff",
padding: "20px",
}}
>
<h2>Current Theme: {theme}</h2>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
}
export default HomePage;
What Happens Here:
The ThemeContext is created using
createContext().The ThemeProvider component wraps your app and provides the theme data.
Inside HomePage, you can access and modify the theme using
useContext.
Advantages of Using Providers
- Centralized data source
- Cleaner and maintainable component tree
- Avoids repetitive prop passing
- Makes global states easier to manage
Common Mistakes
- Forgetting to wrap components inside the Provider → results in
undefineddata. - Nesting too many Providers → leads to Provider hell (hard to manage).
- Overusing Context for every state → can cause unnecessary re-renders.
Best Practices
- Use one context per concern (e.g., UserContext, ThemeContext).
- Combine Context API with custom hooks for cleaner access.
- Wrap your entire app in the Provider inside
index.jsorApp.js.
Example:
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { ThemeProvider } from "./ThemeProvider";
ReactDOM.render(
<ThemeProvider>
<App />
</ThemeProvider>,
document.getElementById("root")
);