Home / Articles / Scope State by Lifetime: When a React Portal Actually Needs a Global Store

This article is published in English.

Scope State by Lifetime: When a React Portal Actually Needs a Global Store

Learn to decide where React portal state belongs by its owner and lifetime, why global stores create cleanup bugs, and which cases truly justify Redux or Zustand.

768 words

Teams building internal portals often open the state discussion with "Redux or Zustand?" A more useful first question is which pieces of state genuinely need to be global at all. This article shows how to classify portal state by who owns it and how long it should live, why putting short-lived state in a global store creates a steady stream of cleanup bugs, and when a global library is the right call.

Most portal state is short-lived

Portals tend to be collections of separate workflows. A user opens a page, searches or edits something, finishes the task and moves to another area of the app. Form values, filters, selected table rows, the active tab and whether a modal is open all belong to that page or workflow. They rarely need to persist across several unrelated routes.

Only a small set of data is truly application-wide:

  • the signed-in user;
  • authentication state and permissions;
  • the current organisation or tenant;
  • theme and language preferences.

Almost everything else should stay close to the feature that owns it.

Global stores turn lifetime into a cleanup job

Put temporary state into Redux, Zustand, MobX or any other global store and it outlives the screen that created it. Now you need extra code to reset it on navigation, after submission, on logout, when the tenant changes and on every other exit path. Miss one path and a user returns to a screen that shows stale filters, old selections or half-filled form values from a previous visit. These bugs are hard to reproduce because they depend on the exact sequence of screens the user visited.

The rule of thumb that follows is short: if global state constantly has to be cleared so that it behaves like local state, it should probably have been local from the start.

Pick the smallest scope that fits

Match each piece of state to the narrowest tool that covers its lifetime:

  • component state for UI behaviour that concerns a single component;
  • React Context for state shared across one feature or a group of related routes;
  • URL search parameters for filters, pagination and other navigation state, which also makes views shareable and survives a refresh;
  • a server-state library such as TanStack Query for data fetched from the backend, since caching and invalidation are its job rather than your store's;
  • a global store only for client state that is genuinely application-wide.

Route-level Context deserves special mention. When you place a provider around a group of routes, leaving that group unmounts the provider and its state disappears automatically. React's component lifecycle does the cleanup that you would otherwise write by hand. If the concern driving you towards a store is really passing props through many layers, that is a separate problem with lighter solutions, covered in why prop drilling is not a reason to install Redux or Zustand.

When a global store earns its place

Redux, Zustand and similar libraries are the right choice when state is meant to survive across unrelated screens on purpose. Typical cases include:

  • shopping carts;
  • complex checkout flows that span several pages;
  • drafts that must persist;
  • offline-first applications;
  • app-wide messaging or notification systems;
  • undo and redo;
  • real-time features where client state must be coordinated;
  • intricate workflows with many interdependent state transitions.

In these situations, centralised state solves a real problem instead of creating one.

Key takeaways

  • Decide on ownership and lifetime before choosing any library.
  • State that belongs to a single workflow should disappear with that workflow, ideally through unmounting rather than manual resets.
  • Keep server data in a query library and navigation state in the URL.
  • Reserve a global store for state that the whole application intentionally shares over time; knowing when not to use one is part of good architecture.