Under The Hood
frontend react React 18 / 19

React Context: Sub-Tree Re-Render Cost and Selector Memoization

Last updated
Prerequisites:
React Context API
React.memo and useMemo
  • react
  • context
  • memoization
  • re-render
  • performance
  • useContext

Read at your depth

The practical view

When a Context Provider's `value` changes (by reference equality `Object.is`), **every component calling `useContext(MyContext)` will re-render**, even if the component only cares about an untouched field inside the context object. Wrapping consumers in `React.memo()` does **not** stop context-triggered re-renders. To optimize, split large contexts into smaller, specialized contexts or memoize sub-components.

The same idea in other frameworks

react equivalent
Splitting State / Dispatch contexts or using `use-context-selector`.

Legacy vs modern

Monolithic Context (Over-rendering) vs Split Context Architecture

Monolithic context objects trigger re-renders on unrelated consumers; splitting state and dispatch prevents wasteful rendering.

before → after
Monolithic Context Object
<UserContext.Provider value={{ user, setUser, theme, setTheme }}> // ❌ Renders all consumers on any change
Split Context Architecture
<ThemeContext.Provider value={theme}><UserContext.Provider value={user}> // ✅ NEW

Interview gotchas

Context

This is one of the most common React performance interview traps.

The mechanical answer

No. `React.memo` only prevents re-renders when a component's **props** are unchanged. If a component calls `useContext(MyContext)` and the Provider's value changes, React will **always** re-render that component, completely bypassing `React.memo`.

Trap

To prevent child subtrees from re-rendering, you must extract the context-consuming hook into a parent component and pass the extracted value down to a memoized child component via props.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.