Migration Guides
From a hook-based server-state library
If your data fetching is built on the useQuery/useMutation pattern — a query-key cache, staleTime, refetchOnWindowFocus, invalidateQueries — this page covers what carries over almost unchanged, and the three gaps in that model that Flux exists to close: hard reload, offline, and multi-tab.
Prerequisites
- An existing setup using a hook-based server-state / data-fetching library (query keys, mutations, cache invalidation)
- A state manager Flux can write into — Zustand, Redux, or Jotai — see state-managers/zustand
- Familiarity with api/register and api/bootstrap on the client side
1
The pattern, not the library
This isn't about one specific package — it's the shape nearly every hook-based server-state library converges on: a query key becomes a cache key, a mutation gets optimistic updates and invalidation. For a huge range of apps this is genuinely the right tool. This page is about what happens at the edges of that model.
typescript
2
Where the two models overlap almost exactly
A query key and a Flux channel are doing structurally the same job. This is not a rip-and-replace migration — most of the mental model transfers directly.
typescript
3
Gap 1 — staleTime doesn't survive a reload
staleTime only helps within a session. A hard reload throws the whole in-memory cache away, every time, for every user.typescript
4
Gap 2 — refetchOnWindowFocus fires blind
It exists because there's no other freshness signal available. With a realtime adapter registered, most focus events resolve with zero network calls instead of one guaranteed refetch.
typescript
5
Gap 3 — offline mutations have no home
This is the gap that matters most in practice.
onError rolls back an optimistic update, but the user's edit is simply gone unless something persists and retries it.typescript
6
Gap 4 — no cross-tab awareness
Two tabs on the same page hold two independent caches by default, with no communication between them unless it's built by hand.
typescript
7
Cache invalidation, mapped directly
Same intent, same escape hatch, different name.
typescript
8
What doesn't change
Request-level concerns that were never this library's job, or Flux's job either — no reason to touch these during migration.
typescript
9
When this migration isn't worth it
Worth checking per-screen before migrating anything wholesale.
typescript
10
Migrating incrementally
Both models can coexist. Migrate the screens that actually feel the reload/offline/multi-tab pain first and leave the rest where it is.
typescript
No all-or-nothing requirement
A store's registration and bootstrap call are independent of every other registered store — there's no global switch that forces the whole app onto Flux at once.
For what a browser-native cache does and doesn't replace in general, see core-concepts/what-flux-is-not. For the offline queue mechanics referenced in Step 5, see core-concepts/offline-queue. For cross-tab leader election referenced in Step 6, see core-concepts/browser-physics.