React Context Provider Component

In the last lesson, React Creating Context, you made a context object, but it’s still empty. This lesson uses the context’s Provider to wrap part of your app and give it a real value, so every component inside can read that shared data.

🤔 What is the Provider?

The Provider is the component that supplies the actual value for a context to everything inside it.

  • Every context object comes with a .Provider component built in.
  • You wrap a part of your tree in it and pass a value prop.
  • Every component inside that wrapper can now read that value.
  • Components outside the Provider can’t see it, so they fall back to the default.

So the Provider is the “fill” step. Creating the context made the empty box, and the Provider puts something in it for a section of your app.

🧩 Using the Provider

You take the context you created and wrap your components in its .Provider, passing a value.

import { ThemeContext } from "./ThemeContext";
function App() {
return (
<ThemeContext.Provider value="dark">
<Page />
<Sidebar />
</ThemeContext.Provider>
);
}

Here’s what’s happening:

  • ThemeContext.Provider is the provider that comes with the context.
  • The value="dark" prop is the actual data being shared, here the string "dark".
  • Everything inside, so Page and Sidebar and whatever they contain, can now read "dark".
  • The default "light" from createContext is ignored here, because the Provider’s value wins.

The value prop is required

The Provider needs a value prop. That’s the data it shares. Without it, the provider passes undefined, not the default. So always pass value.

🎁 Sharing more than one value

Often you want to share several related things, like a value plus a function to change it. You bundle them into an object and pass that as the value.

import { useState } from "react";
import { ThemeContext } from "./ThemeContext";
function App() {
const [theme, setTheme] = useState("light");
// share both the value and a way to change it
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Page />
</ThemeContext.Provider>
);
}

See how the bundle works:

  • We keep the real theme in state with useState, so it can change.
  • We pass an object, { theme, setTheme }, as the value.
  • Now any component inside can read both the current theme and the setTheme function to change it.
  • Because theme is state, changing it re-renders everything that reads the context with the new value.

So putting an object in value lets you share a whole bundle: the data and the tools to update it. This is the common real-world pattern.

🌳 Where to put the Provider

Where you wrap matters, because only the components inside the Provider can read the value.

  • Put the Provider high enough to cover every component that needs the data.
  • For app-wide data like theme, that’s usually near the very top, around the whole app.
  • Components outside the Provider can’t read it, so don’t wrap too narrowly.
  • But you don’t have to wrap the entire app if only one section needs the data.

So the rule is simple. Wrap the smallest part of the tree that still covers everyone who needs the value. For truly global data, that’s the top.

// often the Provider goes at the very top, wrapping everything
function App() {
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Header />
<MainContent />
<Footer />
</ThemeContext.Provider>
);
}

⚠️ Common Mistakes

A common mistake is forgetting the Provider entirely, so readers silently get the default.

// ❌ no Provider anywhere - every reader gets the default, not your data
function App() {
return <Page />; // Page's useContext returns the default "light"
}
// ✅ wrap in the Provider so readers get the real value
function App() {
return (
<ThemeContext.Provider value="dark">
<Page />
</ThemeContext.Provider>
);
}

Keep these in mind:

  • Don’t forget to wrap. Without a Provider, every reader falls back to the default.
  • Don’t forget the value prop. The Provider needs it to share anything.
  • Don’t wrap too narrowly. The Provider must be above every component that reads the context.

✅ Best Practices

A few habits for providers:

  • Wrap the part of the tree that covers everyone who needs the data; for global data, the top.
  • Bundle related data and updater functions into one object as the value.
  • Keep the shared value in state, so changing it re-renders the readers automatically.
  • Use one Provider per context, placed once where it makes sense.

A custom provider component is cleaner

Once your provider has state and logic, many people wrap it in a small custom component, like ThemeProvider, that holds the state and renders the Provider. You’ll often see that pattern, and it keeps App tidy. The idea is the same: it renders the context’s Provider with a value.

🧩 What You’ve Learned

  • ✅ The Provider supplies the real value for a context to everything inside it
  • ✅ Every context has a built-in .Provider; wrap your tree in it and pass a value prop
  • ✅ Components inside can read the value; components outside get the default
  • ✅ Bundle related data and updater functions into an object for the value
  • ✅ Keep the value in state so changing it re-renders the readers
  • ✅ Place the Provider above every component that needs the data; for global data, near the top

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does the context Provider do?

    Why: The Provider fills the context with a real value via its value prop. Every component inside the Provider can then read that value.

  2. 2

    How do you share both a value and a way to change it through context?

    Why: Bundle them into an object and pass it as the value, like value={{ theme, setTheme }}. Then readers get both the data and the updater function.

  3. 3

    What happens to components outside the Provider?

    Why: Only components inside the Provider can read its value. Components outside it get the default passed to createContext.

  4. 4

    Why keep the shared value in state inside the Provider?

    Why: When the value is state and it changes, React re-renders every component that reads the context with the new value, keeping the UI in sync.

🚀 What’s Next?

Now you can provide a value to a whole section of your app. Next we’ll put it all together into real shared global state, where one piece of state lives in context and many components read and update it.

React Sharing Global State

Share & Connect