The Context Performance Trap

Why you should never use React Context for rapidly changing data, and how it can silently destroy your app's performance.

React5 min readConcept 22 of 46

The Re-render Rule

Whenever the value prop of a <Context.Provider> changes, React completely bypasses the normal rendering flow.

It searches the entire component tree and **forces every single component that calls useContext() to re-render immediately.**

Crucially, it does this even if you try to stop it with React.memo or shouldComponentUpdate. Context updates are a sledgehammer.

The Performance Trap

Imagine you build an AppGlobalContext and you store the user's current scroll position in it, so a specific nav bar can change color.

Because the scroll position updates 60 times a second, the Context value changes 60 times a second.

This forces every single component that consumes AppGlobalContext (which might be 50 different components) to re-render 60 times a second. Your app will grind to a halt.

How to fix it

**1. Split your Contexts:** Don't put everything into one giant GlobalContext. Put the theme in ThemeContext and the user in UserContext. This way, a theme change doesn't re-render components that only care about the user.

**2. Keep fast data out:** Never put rapidly changing data (scroll position, mouse coordinates, ticking clocks, real-time sockets) into Context. Use a specialized global state manager like Zustand, Redux, or Jotai for that.

The Re-Render Cascade

Turn on the fast-updating state. Notice how every single component that consumes the context flashes red, indicating a forced re-render, even if it doesn't care about that specific piece of data!

const GlobalContext = createContext(null);
 
function App() {
const [tick, setTick] = useState(0); // Updates fast!
const [theme, setTheme] = useState('Light');
 
// BAD: New object literal on every render
// BAD: Mixing fast data with slow data
return (
value={{ tick, theme }}>
);
}
Provider State Controls
Fast Consumer0Reads 'tick'
Slow Consumer ALightReads 'theme'
Slow Consumer BLightReads 'theme'

Click 'Start Fast Data'. Notice how the Slow Consumers flash red indicating a re-render. Even though they only care about 'theme', the rapidly changing 'tick' in the shared context forces them to re-render constantly!

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1What happens when a Context Provider's value changes?
  2. 2Why is `<Provider value={{ count, setCount }}>` a potential performance trap?
  3. 3What is the best way to handle global state that changes 60 times a second (e.g., mouse coordinates)?

Remember this

  • Context forces EVERY consumer to re-render when the value changes.
  • Never put rapidly changing data in Context.
  • Split large contexts into smaller, specialized contexts.
  • Always wrap object values in useMemo before passing them to a Provider.

Done with this concept?

Mark it complete to track your progress. No login needed.