Guides
Important defaults
When raf-query fetches, refetches, retries and garbage-collects by default, and which options change it.
Out of the box, raf-query is configured with aggressive but sane defaults, the same ones TanStack Query uses. They can catch you off guard if you don't know them, so keep them in mind as you read the rest of the guides:
-
Cached data is stale immediately (
staleTime: 0). -
Stale data refetches in the background when:
- a loader or server component starts the query again (
prefetch,ensureorfetch), which TanStack Router does on every navigation - the window becomes visible again (window focus refetching), for queries being read
- the browser comes back online, for queries being read
- the query is invalidated
- a loader or server component starts the query again (
-
Mounting a component never fetches. Unlike TanStack Query, raf-query has no refetch on mount: whatever started the query decides when it loads. Rendering the same handle in ten components reads one cache entry.
-
Polling is per read.
useQuery(factory, handle, { refetchInterval })refetches on a timer while that component is mounted and the page is visible, independent ofstaleTime. See Polling. -
Unread entries are kept for five minutes (
gcTime: 300_000). An entry nobody reads is inactive: it stays in the cache in case it's needed again, then is garbage-collected. -
Failed requests retry three times, with a delay that doubles from one second, up to 30 seconds, before the error reaches the UI. Retries wait while the browser is offline. See Retries.
-
Data is structurally shared. When a refetch returns data that's deeply equal to what's cached, the cache keeps the old objects, so unchanged parts keep their identity and nothing re-renders. See Render optimizations.
On the server
A server client (one per request) renders once, so it behaves differently:
- Cached data is always reused, whatever
staleTimesays. A background refetch on the server could only repeat a request whose result is never shown. Entries marked byinvalidatestill refetch. - No retries (
retry: 0) and no garbage collection (gcTime: Infinity): the cache lives as long as the request. useIsFetching()returns0, so loading indicators never appear in server HTML.
Changing the defaults
Every option can be set per query in the factory, or for every query with config.defaults. A query's own option wins:
const const queryClient: QueryClient<never>queryClient = new new QueryClient<never>(config?: QueryClientConfig<never>): QueryClient<never>QueryClient({
Config.defaults?: QueryBehavior | undefineddefaults: {
QueryBehavior.staleTime?: number | undefinedstaleTime: 30_000,
QueryBehavior.gcTime?: number | undefinedgcTime: 10 * 60_000,
QueryBehavior.retry?: RetryPolicy | undefinedretry: 1,
QueryBehavior.refetchOnWindowFocus?: boolean | undefinedrefetchOnWindowFocus: false,
},
});| Option | Default |
|---|---|
staleTime | 0 ms |
gcTime | 5 minutes; Infinity on the server |
retry (count, boolean, predicate, Schedule) | 3; 0 on the server |
retryDelay (ms, or a function of the count) | Doubling from 1 s, at most 30 s |
refetchOnWindowFocus, refetchOnReconnect | true (only read, stale queries refetch) |
structuralSharing | true |
enabled | true; false disables it, such as on the server |
meta | None |
Watch the defaults at work in Caching, which has a live demo of an entry going from fresh to stale to garbage-collected.