React State Options: Context vs Redux Toolkit vs Zustand React's version of the state decision tree runs into one specific misconception more than any other: that Context is a state manager. It isn't. Context is React's version of Angular's dependency injection — a distribution mechanism, moving a value to wherever it's needed without threading it through every intermediate prop. It has no update-batching intelligence beyond what React already does, no devtools, no middleware, and critically, no way for a component to subscribe to just part of what it holds. Understanding that gap is most of this lesson. Mapping the tree onto React's toolkit Levels 1–2 (local, lifted): . In the component, or lifted to the nearest common parent and passed down as props. Level 3 (shared, cross-cutting): Context. plus a provider, for genuinely stable, infrequently-changing, broadly-needed data — the current user, the active theme, a feature flag. Level 4 (global store, many writers, needs devtools): Redux Toolkit or Zustand. Redux Toolkit is the more opinionated, more structured option — actions, reducers, middleware, mature devtools, a good fit when a feature has many writers and update logic complex enough to need that structure. Zustand is the lighter-weight middle ground — a store with far less ceremony, a good fit for teams that want selector-based subscriptions and simple update logic without Redux's full architecture. Level 5 (server state): TanStack Query. Covered in the previous lesson. Why Context specifically breaks down under frequent updates The gap that catches teams out: Context has no selective subscription. Every component consuming a Context re-renders whenever the Context's value changes — even if that component only cares about one field inside it. A Redux or Zustand store, by contrast, lets a component subscribe to a specific slice via a selector, and only that component re-renders when that slice changes. For data that rarely changes — theme, locale, the logged-in user — this doesn't matter, because updates are rare enough that broad re-rendering is cheap. For data that changes on every keystroke or every frame, it matters enormously. The Trade-off: Is Context Ever the Wrong Choice — and When? Context feels like the "React-native" answer to almost any sharing problem, since it ships with the framework and needs no extra dependency. Whether that's the right call depends entirely on how often the value changes and how many components are watching it. The pain, concretely v1: A form's field values are lifted into a Context so a sidebar preview panel can show them live as the user types. Two consumers, feels reasonable. v2: The form grows to ten fields. Every keystroke in any field now re-renders every consumer of that Context — the whole form, the preview panel, a validation summary — because Context has no mechanism to subscribe to just one field. v3: Performance profiling shows the app re-rendering hundreds of times during a routine form fill. gets added everywhere as a band-aid, which only partially helps, because the Context value object itself is a new reference on every render regardless of memoization downstream. v4: The team finally splits the Context into several smaller ones, or migrates the form's state to Zustand with field-level selectors — which is what should have been reached for the moment the value started changing on every keystroke and being read by several components at once. Side-by-side Context for frequently-changing data A store with selectors --- --- --- One field changes Every consumer of the Context re-renders Only the component subscribed to that field re-renders Debuggability None built in Devtools, action logs (Redux Toolkit), or simple traceable updates (Zustand) Setup cost None — ships with React A dependency, and a small amount of store setup Right use case Stable, infrequently-changing, broadly-needed data Frequently-changing data read by many components The signal to switch The moment a Context is holding a value that changes frequently and is read by several components — that's the trigger to reach for a proper state library instead. Context's sweet spot is the opposite: stable, infrequently-changing, broadly-needed data. Start simple Context is not a mistake — for the right data, it's the correct default. Theme, locale, the current user: reach for Context first, and don't add Redux or Zustand until a value's change frequency and consumer count both climb high enough that broad re-rendering becomes a real, measured problem. The rule Context is a distribution mechanism, not a state manager — right for stable, infrequently-changing, broadly-needed data, wrong for anything that changes frequently and is read by many components, because it has no selective-subscription model. Reach for Redux Toolkit or Zustand — not more Context — the moment a value's change frequency and consumer count both go up.