Suggest an editImprove this articleRefine the answer for “Re-rendering child elements”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)When the value passed to `<Context.Provider value={...}>` changes, **React re-renders all components** that use that context through `useContext()` or `<Context.Consumer>`. **Key point:** React compares the new value with the previous one **by reference, not by content**, so even a newly created object with identical content triggers a re-render of every subscriber.Shown above the full answer for quick recall.Answer (EN)Image## Short answer When the value passed to `<Context.Provider value={...}>` changes, React **re-renders all components** that use that context through `useContext()` or `<Context.Consumer>`. --- ## Why this happens Because **Context is a global subscription mechanism**. React does roughly the following: 1. Every context has a *list of consumers* (components subscribed). 2. When the Provider receives a new `value`, React **compares the new value with the previous one (by reference)**. 3. If the reference changed (`!==`), it **signals all subscribers** that "the value changed". 4. Every component using `useContext()` **re-renders** to get the new value. --- ## The key point: the comparison is **by reference, not by content** ```javascript <ThemeContext.Provider value={{ mode: "dark" }}> <App /> </ThemeContext.Provider> ``` Even if `mode` did not change, `App` creates a **new object** on every render (`{ mode: "dark" } !== { mode: "dark" }`), and React thinks the context value changed -> all subscribers re-render. --- ## How to avoid this - memoizing `value` You need to pass a **stable reference** using `useMemo`: ```javascript function ThemeProvider({ children }) { const [mode, setMode] = useState("light"); const value = useMemo(() => ({ mode, setMode }), [mode]); return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>; } ``` Now the `value` object is created **only when** `mode` changes, not on every render - and the context does not trigger a cascading re-render for nothing. --- ## Analogy You can think of the `Provider` as a "beacon" that tells every subscriber: > "Hey, the value changed, update yourself!" React does not check *what exactly* changed inside the object - it just sees that "the beacon sent a new signal" (a new reference) and updates every subscriber. --- ## What "careless" use of context leads to | Problem | Example | |---|---| | Mass re-renders | One Provider updates 100+ components, and all of them re-render | | Unnecessary computation | Components receive the same value but still recompute | | Performance loss | Especially when passing "heavy" objects in `value` | --- ## Ways to optimize 1. **Split contexts** Do not store everything in one large context - create independent ones: `AuthContext`, `ThemeContext`, `UIContext`, and so on. 2. **Use** `useMemo` **for value** ```javascript const value = useMemo(() => ({ user, setUser }), [user]); ``` 3. **Isolate "heavy" consumers** If the context updates often - wrap part of the UI in `memo` or split out separate Providers. 4. **Use selectors** (for example, with the [use-context-selector](https://github.com/dai-shi/use-context-selector) library) It lets a component subscribe **only to a specific field** of the context, not to the whole `value`. --- ## Summary Updating context causes a re-render of all consumers because React **subscribes them to one shared value** and tracks it **by reference**. This is behavior by design - Context is not meant for "high-frequency" data. To optimize: - memoize `value`, - split contexts, - use specialized solutions (`use-context-selector`, Zustand, Jotai, and so on)For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.