useContext
useContext reads a value from a React context created by createContext. Any component calling useContext(MyContext) re-renders whenever the context value changes. A Provider component higher in the tree supplies the value.
Context is a radio station broadcast — every radio tuned to that frequency (consumer) hears the update, whether they care about the news segment or the weather. Split stations for targeted listening.
Context is designed for data that's global to a subtree — theme, locale, auth status. Every consumer re-renders when the provider's value changes, even if the specific slice they care about didn't change. This is the main performance pitfall: putting a large object in context means every consumer re-renders on any property change. Splitting contexts by update frequency (one for theme, one for user) mitigates this.
React uses the provider's value prop with Object.is comparison to decide whether consumers need updating. If you pass value={{ user, theme }}, a new object is created every render, causing all consumers to re-render — memoize it with useMemo. React 19 simplifies context with Context as a provider directly (<MyContext value={...}>) instead of <MyContext.Provider>. For high-frequency updates (mouse position, scroll), context is too coarse — use external stores with useSyncExternalStore for selective subscriptions.
useContext lets components consume values from a context provider without prop drilling. The gotcha is that ALL consumers re-render when the context value changes, so I split contexts by update frequency and memoize the value object. For high-frequency updates, I prefer external stores with useSyncExternalStore for selective re-rendering.
Passing an object literal as the context value without memoizing it: <Provider value={{ user }}> creates a new object every render, forcing all consumers to re-render even if user hasn't changed.