Skip to main content

Re-render when the context changes

Why all context consumers re-render

When you create a context:

javascript
const ThemeContext = createContext();

and use it like this:

javascript
<ThemeContext.Provider value={theme}> <Header /> <Footer /> </ThemeContext.Provider>

every component inside the Provider that does:

javascript
const theme = useContext(ThemeContext);

subscribes to this value (value).


How the mechanism works

  1. Context.Provider holds one value - value.
  2. Every component calling useContext(ThemeContext) subscribes to that value.
  3. When value changes (by reference), React considers the context updated.
  4. As a result, all subscribed components receive the new value -> React re-renders them with the new context.

Example

javascript
const ThemeContext = createContext(); function App() { const [theme, setTheme] = useState("light"); return ( <ThemeContext.Provider value={{ theme, setTheme }}> <Header /> <Footer /> </ThemeContext.Provider> ); }

When setTheme("dark") is called, value={{ theme, setTheme }} becomes a new object, and React sees that the reference to value has changed, so every component with useContext(ThemeContext) re-renders.


Why this matters

React compares the reference to the object, not its contents:

javascript
value={{ theme, setTheme }}

Every render creates a new object, so the context has "changed".


How to reduce the number of re-renders

If your context holds several values but only one of them changes, you can optimize this.


1. Split the contexts

Instead of one large context:

javascript
<AppContext.Provider value={{ user, theme, language }}>

split it into several:

javascript
<UserContext.Provider value={user}> <ThemeContext.Provider value={theme}> <LangContext.Provider value={language}> <App /> </LangContext.Provider> </ThemeContext.Provider> </UserContext.Provider>

Now changing the theme will not re-render UserContext consumers.


2. Memoize value with useMemo

So the Provider does not create a new object on every render:

javascript
const value = useMemo(() => ({ theme, setTheme }), [theme]); return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;

Now the reference to value is stable, the context updates only when theme changes, not on every render of the parent.


3. Nest consumers deeper

If the context is used only in part of the UI, place the Provider closer to where it's used so fewer components depend on it.


How React thinks about it

React follows this principle:

"If the context value has changed, I must update every component that uses it so they reflect the current data."

This guarantees UI consistency, but it can create unnecessary re-renders if not optimized.


Summary

QuestionAnswer
Why do all consumers re-renderBecause the reference on Provider.value changed (React considers the value new)
What exactly React checksNot the content, but the reference (Object.is(valueOld, valueNew))
How to avoid itMemoize value with useMemo or split the contexts
When it's not a problemWhen the context is small and rarely updates
When it needs optimizingWhen one change triggers a render of dozens of components

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.