🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
REFERENCEreact

react Documentation

LOADING ENGINE...

Provider

AI & DATA SCIENCE // provider

A Context.Provider component supplies a value to be read by any descendant component via useContext, and re-supplying a new value causes all consuming descendants to re-render.

Syntax

<MyContext.Provider value={someValue}>
  {children}
</MyContext.Provider>

Deep Dive Course

Every context object created with createContext() comes with its own Provider component, which accepts a value prop, the actual data being shared, and renders its children normally, making that value available to any useContext(MyContext) call anywhere within those children, no matter how deeply nested. Multiple Providers for the same context can be nested, with a descendant's useContext call always reading from the nearest enclosing Provider above it in the tree, and if the value prop passed to a Provider is a new object or array on every parent render, even with logically identical contents, every consuming component re-renders unnecessarily, since object/array equality is checked by reference, not by deep content comparison.

1Understanding Provider

Every context object created with createContext() comes with its own Provider component, which accepts a value prop, the actual data being shared, and renders its children normally, making that value available to any useContext(MyContext) call anywhere within those children, no matter how deeply nested. Multiple Providers for the same context can be nested, with a descendant's useContext call always reading from the nearest enclosing Provider above it in the tree, and if the value prop passed to a Provider is a new object or array on every parent render, even with logically identical contents, every consuming component re-renders unnecessarily, since object/array equality is checked by reference, not by deep content comparison.

💡

Wrap a Provider's value prop in useMemo when it's an object or array constructed inline in the parent's render, otherwise a brand-new object reference on every render causes every consuming component to unnecessarily re-render, even if the object's actual contents haven't logically changed.

editor.html
const CountContext = createContext(0);

function App() {
  return (
    <CountContext.Provider value={5}>
      <Display />
    </CountContext.Provider>
  );
}

function Display() {
  const count = useContext(CountContext);
  return <p>Count: {count}</p>;
}
localhost:3000

2Practical Example

Here is a real-world application of Provider showing how it is used in production React code.

editor.html
const ThemeContext = createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Section />
      <ThemeContext.Provider value="light">
        <NestedSection />
      </ThemeContext.Provider>
    </ThemeContext.Provider>
  );
}
localhost:3000

3Best Practices

Follow these guidelines when working with Provider:

1. Memoize a Provider's value prop with useMemo whenever it's an object or array, to avoid giving every consumer a new reference, and therefore an unnecessary re-render, on every parent render

2. Nest multiple Providers for the same context deliberately when you specifically need different parts of the tree to see different values, since the nearest enclosing Provider always wins

3. Keep a Provider as close as reasonably possible to the components that actually need its value, rather than always wrapping the entire application, to limit the scope of re-renders it can trigger

⚠️

Tip: Wrap a Provider's value prop in useMemo when it's an object or array constructed inline in the parent's render, otherwise a brand-new object reference on every render causes every consuming component to unnecessarily re-render, even if the object's actual contents haven't logically changed.

editor.html
const CountContext = createContext(0);

function App() {
  return (
    <CountContext.Provider value={5}>
      <Display />
    </CountContext.Provider>
  );
}

function Display() {
  const count = useContext(CountContext);
  return <p>Count: {count}</p>;
}
localhost:3000

Examples

Example 01Basic Usage
const CountContext = createContext(0);

function App() {
  return (
    <CountContext.Provider value={5}>
      <Display />
    </CountContext.Provider>
  );
}

function Display() {
  const count = useContext(CountContext);
  return <p>Count: {count}</p>;
}
Example 02Advanced Example
const ThemeContext = createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Section />
      <ThemeContext.Provider value="light">
        <NestedSection />
      </ThemeContext.Provider>
    </ThemeContext.Provider>
  );
}

Best Practices

  • Memoize a Provider's value prop with useMemo whenever it's an object or array, to avoid giving every consumer a new reference, and therefore an unnecessary re-render, on every parent render
  • Nest multiple Providers for the same context deliberately when you specifically need different parts of the tree to see different values, since the nearest enclosing Provider always wins
  • Keep a Provider as close as reasonably possible to the components that actually need its value, rather than always wrapping the entire application, to limit the scope of re-renders it can trigger

Interview Question

Why does passing a newly-created object as a Provider's value prop on every render cause unnecessary re-renders in every consuming component, even if the object's actual contents never logically change?

Hint: Think about how React (and JavaScript in general) compares object values for equality — by their contents, or by their reference in memory?

React's context mechanism determines whether a Provider's value has changed using reference equality, essentially the same check as ===, not a deep comparison of the object's actual properties and their values — two separately created objects are never considered === to each other in JavaScript even if every one of their properties holds identical values, since each object literal creates a genuinely distinct object in memory. If a Provider's value prop is written as an inline object literal directly in the parent component's JSX, like value={{ user, theme }}, a brand new object gets created on every single render of that parent, meaning the value changes by reference on every render even when user and theme themselves haven't actually changed, causing every component consuming that context to re-render unnecessarily. Wrapping that object construction in useMemo, keyed on the actual underlying values it depends on, ensures the same object reference is reused across renders unless one of those underlying values genuinely changes, correctly avoiding those unnecessary re-renders.

Exercises

MediumPractice using Provider in a real scenario.
View Solution
const CountContext = createContext(0);

function App() {
  return (
    <CountContext.Provider value={5}>
      <Display />
    </CountContext.Provider>
  );
}

function Display() {
  const count = useContext(CountContext);
  return <p>Count: {count}</p>;
}

Frequently Asked Questions

Why does passing a newly-created object as a Provider's value prop on every render cause unnecessary re-renders in every consuming component, even if the object's actual contents never logically change?

React's context mechanism determines whether a Provider's value has changed using reference equality, essentially the same check as ===, not a deep comparison of the object's actual properties and their values — two separately created objects are never considered === to each other in JavaScript even if every one of their properties holds identical values, since each object literal creates a genuinely distinct object in memory. If a Provider's value prop is written as an inline object literal directly in the parent component's JSX, like value={{ user, theme }}, a brand new object gets created on every single render of that parent, meaning the value changes by reference on every render even when user and theme themselves haven't actually changed, causing every component consuming that context to re-render unnecessarily. Wrapping that object construction in useMemo, keyed on the actual underlying values it depends on, ensures the same object reference is reused across renders unless one of those underlying values genuinely changes, correctly avoiding those unnecessary re-renders.

Related Functions

context-apiusecontextusememo