Add one momo, re-render the whole shop
Context cures prop drilling — the field guide's chapter on state management shows how passing a value through five components that don't use it makes every change touch all five files. So teams put the cart in context. Then the profiler shows something odd: clicking Add re-renders every *Add* button, the header, the footer… every component that reads the cart context, even the ones that only ever call add.
Context isn't slow, but it has one simple rule, and at scale you have to design around it. Learn the rule and three small techniques, and a provider can sit at the top of a large app without causing re-render storms.
The rule: a new value re-renders every consumer
When a provider's value changes, React re-renders every component that calls useContext for that context — no matter which part of the value it uses. "Changes" means referential equality: React compares the old and new value with Object.is. An object literal written in render is a brand-new object every time, so this provider tells every consumer "changed!" on every render:
function CartProvider({ children }) {
const [items, setItems] = useState([]);
const add = (name) => setItems((list) => [...list, name]);
return (
<CartContext.Provider value={{ items, add }}>
{children}
</CartContext.Provider>
);
}The children prop is your friend: elements passed in from above are the same objects on every provider render, so React skips them unless they read the context. Keep providers small and pass the tree through children.