SOFTWARE / SYSTEMS / AIEngineering news. Technical depth.
Architecture / 3 MIN READ

Give Every Piece of Frontend State One Durable Owner

Place state by authority, shareability, lifetime, sensitivity, synchronization, and reset behavior, then derive all secondary views.

Choose one authoritative owner for each piece of frontend state, then derive or cache every other representation. Put shareable navigation state in the URL, server facts in the server-backed query cache, ephemeral interaction state near the component, durable local preferences in browser storage, and authenticated authority on the server. Duplication creates synchronization bugs.

Decide with six questions

Ask who is authoritative, whether the value should survive reload, whether a copied URL should reproduce it, whether another tab must see it, whether it is sensitive, and what event resets it. These answers usually identify the owner. A filter intended for bookmarking belongs in query parameters. An unsaved modal tab belongs in component state. A fetched invoice remains a server fact even when a client cache holds a copy.

The URL is excellent for search text, page, sort, selected resource, and view mode when sharing should reproduce the view. Parse and validate it on navigation. Use stable identifiers, omit defaults, and update history deliberately: replace while typing noisy filters, push for meaningful navigational steps. Never put secrets or bearer credentials in URLs because browsers, logs, referrers, and screenshots can retain them.

Browser storage suits non-sensitive preferences and recoverable drafts. MDN documents that localStorage persists across browser sessions, is scoped to an origin, stores strings, and can be unavailable due to browser policy. Treat reads as untrusted: parse, validate, version, and tolerate absence. Do not use it as the authority for roles, entitlements, prices, or session validity.

Keep server state as server state

A query cache owns freshness policy and a copy of remote facts, while the server remains authoritative. Mutations should update or invalidate the cache through one path. Copying a fetched record into a global application store creates two caches with different lifetimes. The result is a customer name updated in one view and stale in another.

For editable forms, create an explicit draft initialized from a server revision. Track dirty fields and submit with a version or conditional request so concurrent updates become conflicts rather than silent overwrites. After success, replace the cached server value and reset the draft. A draft has a different owner and lifecycle from the record it edits.

React’s state-structure guidance recommends avoiding contradictory, redundant, and duplicated state and deriving values that can be calculated during rendering. The principle extends beyond component variables: do not store isAdmin when it is derived from current permissions, or both selectedId and a copied selected object that can diverge.

Model reset and synchronization

Component state resets when the component or its identity changes. URL state resets when navigation removes it. Cached server state expires or invalidates by query key. Local storage needs explicit logout, account-switch, schema-version, and retention behavior. An application store should own only cross-cutting client state with a clear lifetime, not become the default destination for every value.

Multiple tabs make ownership visible. URL state is tab-local; local storage is shared by origin and emits storage events to other documents; server state converges through refetch or push. Decide which behavior each value needs. A tenant selection stored globally can make one tab change another’s context, while a theme preference should often synchronize.

Review concrete examples

Put product filters and pagination in the URL. Keep hover, open menus, and current input composition local. Store an autosaved draft on the server when users expect cross-device recovery; use local storage only for best-effort recovery with an age and account key. Keep authentication in protected cookies or the identity layer and fetch current session state rather than copying it into several stores.

The next step is to inventory one screen’s state variables and label each with authority, lifetime, reset event, and derived copies. Delete one duplicate representation and add a test for reload or account switch. Review by 2026-12-05 or after state-management architecture changes.

SOURCES & REVIEW

Sources are linked throughout this guide. Product capabilities can change; consult the linked documentation for your deployment.

Read our editorial approach ↗