Frontend State Management concept page covering server state (TanStack Query), client/UI state (Zustand), URL state (Next.js searchParams), and form state (React Hook Form). Includes 2 ADRs (Zustand vs Redux Toolkit vs Jotai for 2026; TanStack Query vs SWR vs custom useEffect) and 3 scenarios: local state lifted to Zustand, server state cache+refetch+mutation+invalidation, URL state filters with TanStack cache reuse.
State management начинается не с выбора библиотеки, а с определения authority и lifetime. Локальный UI state, shared client state, URL state и кэш server-owned data имеют разные правила обновления, persistence и invalidation.
React рассматривает state текущего render как snapshot и может batch обновления. Асинхронный ответ поэтому обязан проверять identity/version запроса, а derived data лучше вычислять из канонического источника, не хранить второй независимой копией.
| Компонент | Роль в модели |
|---|---|
| User and Route Events | local intent; shared command |
| Local UI State | local intent; read derivation; query subscription |
| Shared Client Store | shared command; read snapshot; explicit persisted subset |
| Pure Derived Selector | read derivation; read snapshot |
| Versioned Query Cache | query subscription; fetch and mutate |
| Authoritative Data API | fetch and mutate |
| Scoped Client Persistence | explicit persisted subset |
A disclosure toggle belongs to one component subtree. The event updates local state with a functional updater and does not enter the global store or durable persistence.
Проверяемый исход: The state resets with the intended component identity and cannot leak into another account or route.
A shared command replaces normalized entities immutably. Components read a memoizable selector instead of maintaining a second writable total or filtered list.
Проверяемый исход: One canonical client snapshot produces all derived views; no duplicated field can drift after a batched update.
The query layer records an operation identity, renders an optimistic projection, sends the mutation, then replaces or invalidates the projection from the authoritative result.
Проверяемый исход: Success, rejection and retry all converge on a server-confirmed version; an optimistic view is never described as a committed server fact.
A route or search key changes while an older request is in flight. The query cache compares the response identity with the active key before publishing it.
Проверяемый исход: A late response can populate its own keyed cache entry but cannot overwrite the currently selected resource.
cache_bytes ≈ live_entries × mean_serialized_bytes + index_and_runtime_overhead; measure the overhead rather than assuming the serialized size is total memory.n records is O(n). Memoization changes repeated-work cost only when its identity assumptions hold.staleness_age = observation_time − authoritative_version_time; it is different from request latency and requires comparable clocks or a server-issued timestamp/version.Числа и bounds выше действуют только при названных units, population и assumptions. Ни паттерн, ни browser API сами по себе не задают SLA, capacity или correctness.
Диаграмма использует React terminology для snapshot/batching, но не объявляет Redux, Context, Zustand или query library универсальным выбором и не моделирует конкретный framework scheduler.
Введите числа или выберите пресет