tanstack-vue-query-skilld
TanStack/query @tanstack/vue-query
Hooks for managing, caching and syncing asynchronous and remote data in Vue
Version: 5.92.9 (Jan 2026) Deps: @tanstack/match-sorter-utils@^8.19.4, @vue/devtools-api@^6.6.3, vue-demi@^0.14.10, @tanstack/query-core@5.90.20 Tags: alpha: 5.0.0-alpha.91 (Jul 2023), beta: 5.0.0-beta.35 (Sep 2023), rc: 5.0.0-rc.16 (Oct 2023), latest: 5.92.9 (Jan 2026), previous: 4.43.0 (Jan 2026)
References: Docs — API reference, guides
API Changes
This section documents version-specific API changes — prioritize recent major/minor releases.
-
BREAKING:
useQuerysignature — v5 requires a single object argument{ queryKey, queryFn, ... }. Old positional arguments are no longer supported and will result in errors source -
BREAKING:
useQueriessignature — v5 now takes an object with aqueriesarray property:useQueries({ queries: [...] }). This allows for additional top-level options likecombine -
BREAKING:
useQueriesreturn type — now returns aRefof the results array instead of areactivearray, ensuring better compatibility with Vue 2 and avoiding spread reactivity loss source -
BREAKING: Callback removal —
onSuccess,onError, andonSettledare removed fromuseQuery,useInfiniteQuery, anduseQueries. Useselectfor data transformation or globalQueryCachecallbacks instead source -
BREAKING:
cacheTimerenamed — renamed togcTime(Garbage Collection time) across all options and default options to better reflect its purpose source -
BREAKING:
useInfiniteQueryparameters —getNextPageParamandgetPreviousPageParamnow receive a single object containinglastPage,allPages,lastPageParam, andallPageParamssource -
BREAKING:
keepPreviousDataremoved — the option is replaced by theplaceholderData: keepPreviousDatahelper function from@tanstack/vue-querysource -
NEW:
queryOptions/infiniteQueryOptions— helper functions for sharing query definitions with type safety across components and for prefetching source -
NEW:
useMutationState— new composable to access mutation state globally by filtering for specific mutations based on keys or filters -
NEW: Options Getter support —
useQueryanduseInfiniteQuerynow support passing a getter function (e.g.,() => options) or aReffor the entire options object, enabling easier reactivity -
NEW:
combineforuseQueries— allows merging multiple query results into a single value (e.g., a single object or a derived state) via thecombineoption -
NEW: Injection Context —
vue-querycomposables can now be used in any function that supportsinjectionContext(e.g., router guards) if used within aneffectScopesource -
DEPRECATED:
isLoading— renamed toisPendingin v5. TheisLoadingproperty now specifically meansisPending && isFetching(fetching for the first time) source -
BREAKING: Vue 3.3 requirement — minimum Vue version for
@tanstack/vue-queryv5 is now 3.3 to support newer reactivity features source
Also changed: isPlaceholderData boolean result new v5 · initialPageParam required for useInfiniteQuery · isPaused property added to query results · Suspense (experimental) supported via suspense() method (experimental)
Best Practices
- Use
MaybeRefOrGetterfor composable parameters to support refs, plain values, and reactive getters seamlessly source
// Preferred: Accepts ref, getter, or value
export function useUser(id: MaybeRefOrGetter<string>) {
return useQuery({
queryKey: ['user', id],
queryFn: () => fetchUser(toValue(id))
})
}
- Pass the entire options object as a getter function to reactively update multiple query parameters at once (v5.91.0+) source
// Preferred for complex reactivity
useQuery(() => ({
queryKey: ['todo', id.value],
queryFn: () => fetchTodo(id.value),
enabled: !!id.value
}))
- Prefer reactive getters over
computedfor simple property access to avoid unnecessary memoization overhead source
// Preferred: No computed needed
const { data } = useUserProjects(() => props.userId)
// Avoid: Unnecessary memoization
const userId = computed(() => props.userId)
const { data } = useUserProjects(userId)
- Use
onServerPrefetchwith thesuspense()helper to ensure queries are awaited during SSR source
const { data, suspense } = useQuery({ queryKey: ['test'], queryFn: fetcher })
onServerPrefetch(suspense)
- Set
staleTimeto a value greater than 0 for SSR to prevent immediate background refetching on the client source
const queryClient = new QueryClient({
defaultOptions: { queries: { staleTime: 1000 * 60 * 5 } }
})
-
Manually call
queryClient.clear()after request handling ifgcTimeis set to a non-Infinity value on the server to prevent memory leaks source -
Treat
useQueryresults as immutable and clone data before using it with two-way bindings likev-modelsource
const { data } = useQuery({ ... })
const model = ref()
watch(data, (newData) => {
model.value = JSON.parse(JSON.stringify(newData))
}, { immediate: true })
- Use the
queryOptionshelper to define type-safe, reusable query configurations that can be shared across components
const userOptions = (id: string) => queryOptions({
queryKey: ['user', id],
queryFn: () => fetchUser(id)
})
useQuery(userOptions('123'))
-
Include all reactive dependencies in the
queryKeyto ensure Vue Query tracks them and refetches automatically on change source -
Utilize a custom
queryClientKeywhen running multiple Vue applications on the same page to prevent QueryClient instance clashing source
// Plugin configuration
app.use(VueQueryPlugin, { queryClientKey: 'AppA' })
// Usage
useQuery({ queryKey: ['data'], queryFn: fetcher, queryClientKey: 'AppA' })