Overview
effector-tanstack-query is a thin adapter that exposes TanStack Query as effector units. It does not reimplement the cache, dedup, or revalidation logic — it forwards them.
What you get
- Stores instead of result objects. Every observer field (
data,status,isPending, …) becomes aStore<T>you cancombineandsamplefrom. - Events instead of imperative methods.
mounted/unmounted/mutate/refresh/fetchNextPageareEventCallables — call them directly or wire them viasample. - Reactive query keys. A
Storeplaced insidequeryKeytriggers a refetch when it updates. No manualinvalidateQueries. - Parallel query families.
createQueries({ source, query })drives a reactive list of queries off a singleStore— items added to / removed from the source spawn / dispose their observers automatically. - SSR via two layers. Hydrate
queryClientwithdehydrate+<HydrationBoundary>AND restore effector scope viaserialize(scope)/fork({ values }). - React entry point. Optional
@effector-tanstack-query/reactpackage shipsuseQuery,useMutation,useSuspenseQuery, etc. — same data, just with auto mount/unmount.
What this is not
- Not a different cache. Behavior, semantics, and options come straight from TanStack Query (
@tanstack/query-core). If TanStack Query supportsstaleTime: Infinity, so do we — same defaults, same edge cases. - Not React-bound. Core works in any environment with effector. React is opt-in via the
/reactsubpackage.
Comparison
| Concept | react-query | effector-tanstack-query |
|---|---|---|
| Read query state | const { data } = useQuery(...) | useUnit(query.$data) or useQuery(query) |
| Reactive key | useState + queryKey: [..., id] | Store directly inside queryKey |
| Trigger fetch | implicit on mount | query.mounted() (or via useQuery hook) |
| Invalidate | queryClient.invalidateQueries(...) | query.refresh() |
| React to outcome | callbacks per mutate(vars, opts) | sample({ clock: m.finished.success, ... }) |
| Parallel queries | useQueries([...]) | createQueries({ source, query }) + useQueries |
| SSR hydration | <HydrationBoundary> | <HydrationBoundary> + fork({ values: ... }) |
Both run on top of the same @tanstack/query-core cache.
Runnable examples
Two reference apps live in examples/ in the repository:
examples/csr— Vite + React. Covers every common pattern: reactive pagination, dependent queries,placeholderData, reactive polling, infinite query, Suspense + ErrorBoundary, mutations + invalidation, optimistic update with rollback, per-call callbacks. MSW handles the mutation endpoints — no backend setup.examples/ssr— Next.js 16 App Router. Per-requestQueryClient+ effector scope,query.prefetchfor awaited SSR prefetching,dehydrate+serialize, hydration with no flash on first paint.