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.Provider wraps your components.

  • The value prop defines what data will be available to consumers.

  • Any component inside Provider can now access theme and setTheme.

Understanding the Provider Flow

Think of the Provider as a data broadcaster:

  • The Provider sends 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:

  1. The ThemeContext is created using createContext().

  2. The ThemeProvider component wraps your app and provides the theme data.

  3. 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 undefined data.
  • 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.js or App.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")
);