Once you create a Context in React, you mainly work with two components: Provider and Consumer.
Together, Provider and Consumer help you implement global state without prop-drilling.
createContext().Consumer to get the value via a function.useContext() hook replaces most Consumer use cases.The Provider component is used to supply data to all components within its scope. Any component nested inside the Provider can access the value it passes.
? Step 1: Create the Context
// ThemeContext: creates a context with "light" as default theme
import React, { createContext } from "react";
const ThemeContext = createContext("light");
export default ThemeContext;
? Step 2: Provide the Value (App.js)
// App component: wraps children with ThemeContext.Provider
import React, { useState } from "react";
import ThemeContext from "./ThemeContext";
import Toolbar from "./Toolbar";
function App() {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Toolbar />
</ThemeContext.Provider>
);
}
export default App;
ThemeContext.Provider wraps <Toolbar />.value prop passes both theme and setTheme to all children.You can also nest multiple Providers like AuthProvider, ThemeProvider, etc., to manage different global states separately.
<App />) so that more components can access the shared data.The Consumer component is an older approach used before React Hooks were introduced. It uses the render props pattern to access the context value.
// Toolbar: consumes ThemeContext using the Consumer component
import React from "react";
import ThemeContext from "./ThemeContext";
function Toolbar() {
return (
<ThemeContext.Consumer>
{({ theme, setTheme }) => (
<div
className={`p-3 text-center bg-${
theme === "light" ? "light" : "dark"
} text-${theme === "light" ? "dark" : "light"}`}
>
<p>Current Theme: {theme}</p>
<button
className="btn btn-primary"
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
>
Toggle Theme
</button>
</div>
)}
</ThemeContext.Consumer>
);
}
export default Toolbar;
<ThemeContext.Consumer> expects a function as its child.{`{ theme, setTheme }`}.theme to set classes and setTheme to toggle between modes.This pattern was common before useContext() made reading context much simpler in function components.
// Conceptual flow of data in React Context
Provider (value) → supplies context
↓
Consumer / useContext() → reads context
↓
UI → updates automatically when value changes
You can use more than one Consumer inside the same component when multiple contexts are involved (for example, theme + authentication).
// Example: reading both ThemeContext and AuthContext
<ThemeContext.Consumer>
{({ theme }) => (
<AuthContext.Consumer>
{({ user }) => (
<p>
{user ? `${user.name}'s Theme is ${theme}` : "Guest"}
</p>
)}
</AuthContext.Consumer>
)}
</ThemeContext.Consumer>
useContext() hook is cleaner and avoids deeply nested Consumers, making the code more readable.| Feature | Provider | Consumer |
|---|---|---|
| Purpose | Supplies context value | Consumes context value |
| Usage | Wraps components | Used inside components |
| API Type | JSX Element | Render Props (pre-Hooks) |
| Modern Alternative | Same usage | useContext() Hook |
Initial state: Theme is "light".
Current Theme: light.After clicking the button:
setTheme switches the value to "dark".Current Theme: dark.No props were passed manually through intermediate components — everything flowed via Context.
<App />).AuthContext, ThemeContext, or UserContext.useContext() wherever possible.UserContext with default name "Guest".App in UserContext.Provider and pass a name value.UserContext.Consumer in another component to display "Welcome, <name>!".
// Practice: simple UserContext with Provider and Consumer
const UserContext = createContext("Guest");
function App() {
return (
<UserContext.Provider value="Meghraj">
<WelcomeBanner />
</UserContext.Provider>
);
}
function WelcomeBanner() {
return (
<UserContext.Consumer>
{(name) => <h2>Welcome, {name}!</h2>}
</UserContext.Consumer>
);
}
Goal: Understand how Provider and Consumer together enable global data flow in React apps without prop-drilling.