Web & frontend · Advanced

State management in a web app

In one line: Most of what's called state is server data stored in the wrong place — separate them and half the complexity disappears.

Four kinds of state

Server data. Lists, items, profile. These are copies of a remote source of truth and need cache treatment: loading, refresh, expiry.

UI state. An open panel, a selected tab, typed text. Lives in the component, dies with it.

Address state. Filter, pagination, search. Its place is in the URL — so it can be shared and navigated back to.

True global state. Logged-in user, theme, language. Very few things.

The common mistake

Putting everything in one global store. The result: every screen depends on every screen, data goes stale without anyone noticing, and bugs that appear only when you reach a screen in a particular order.

When you separate, most of the global code evaporates. What remains is small and easy to understand.

What needs explicit handling

Loading and error states for every fetch, preventing stale requests that return after a newer one, and optimistic updates that know how to roll back when the server refused.

Going deeper

Define one freshness policy per data type — how long a copy is considered valid and when to refresh in the background. Without an explicit policy, every screen invents its own, and then “why isn't this updating” becomes an eternal bug.