$npx -y skills add skilld-dev/vue-ecosystem-skills --skill tanstack-vue-query-skilldHooks for managing, caching and syncing asynchronous and remote data in Vue. ALWAYS use when writing code importing \"@tanstack/vue-query\". Consult for debugging, best practices, or modifying @tanstack/vue-query, tanstack/vue-query, tanstack vue-query, tanstack vue query, query.
| 1 | # TanStack/query `@tanstack/vue-query@5.100.9` |
| 2 | **Tags:** alpha: 5.0.0-alpha.91, beta: 5.0.0-beta.35, rc: 5.0.0-rc.16 |
| 3 | |
| 4 | **References:** [Docs](./references/docs/_INDEX.md) |
| 5 | ## API Changes |
| 6 | |
| 7 | This section documents version-specific API changes — prioritize recent major/minor releases. |
| 8 | |
| 9 | - BREAKING: `useQueries()` returns `Ref<T[]>` instead of `Reactive<T[]>` — Vue 2.7+ compatibility fix that aligns with other composables. Destructuring return value now requires unwrapping ref or using `toRefs()`. Update: `const { data } = useQueries(...)` becomes `const { data } = useQueries(...).value` or `const { data } = toRefs(useQueries(...))[0]` [source](./references/docs/framework/vue/guides/migrating-to-v5.md:L11:22) |
| 10 | |
| 11 | - NEW: Composables support `injectionContext` — `useQuery`, `useMutation`, and other composables can now run in functions with injection context (e.g., router navigation guards), not just component `setup()`. Must use within `effectScope` to prevent memory leaks [source](./references/docs/framework/vue/guides/migrating-to-v5.md:L32:39) |
| 12 | |
| 13 | - NEW: Options getter functions in `useQuery` — pass reactive getters to `queryKey` and `enabled` options to track changes without `computed()`. Example: `useQuery({ queryKey: () => ['posts', userId.value], enabled: () => isReady.value })` [source](./references/releases/@tanstack/vue-query@5.91.0.md) |
| 14 | |
| 15 | - NEW: Options getter functions extended to additional composables — `useInfiniteQuery`, `useMutation`, `usePrefetchQuery`, and `usePrefetchInfiniteQuery` now support reactive getters for all reactive options [source](./references/releases/@tanstack/vue-query@5.92.0.md) |
| 16 | |
| 17 | - NEW: `enableDevtoolsV6Plugin` option for Traditional Devtools — integrate with Vue DevTools v6+ for custom inspector and timeline events. Enable: `app.use(VueQueryPlugin, { enableDevtoolsV6Plugin: true })`. Both v6 and v7 supported [source](./references/docs/framework/vue/devtools.md:L125:139) |
| 18 | |
| 19 | - EXPERIMENTAL: `experimental_createQueryPersister` — persist individual queries to storage (AsyncStorage, LocalStorage, custom). Separate package `@tanstack/query-persist-client-core`. Includes `persistQueryByKey()`, `retrieveQuery()`, `restoreQueries()`, `persisterGc()` utilities. Respects `staleTime` on restore [source](./references/docs/framework/vue/plugins/createPersister.md:L32:44) |
| 20 | |
| 21 | - EXPERIMENTAL: `broadcastQueryClient` plugin — sync query cache across browser tabs and windows via message broadcasting. Experimental API, separate package, subject to change [source](./references/docs/_INDEX.md:L72) |
| 22 | |
| 23 | **Also changed:** Vue 3.3+ now required (was 3.x) · `suspense()` method on useQuery return for explicit await · `VueQueryPlugin` initialization unchanged · Query options now support getters alongside refs and values |
| 24 | <!-- /skilld:api-changes --> |
| 25 | |
| 26 | <!-- skilld:best-practices --> |
| 27 | ## Best Practices |
| 28 | |
| 29 | - Always use `queryOptions()` helper when defining query configurations, rather than passing objects directly to `useQuery` — this enables TypeScript inference, prevents queryKey/queryFn mismatches at runtime, and allows safe reuse with `queryClient` methods like `getQueryData()` and `invalidateQueries()` [source](./references/docs/eslint/prefer-query-options.md) |
| 30 | |
| 31 | - Pass reactive values (Ref or computed) directly into the `queryKey` array, not their `.value` — Vue Query automatically tracks reactive dependencies and refetches when they change [source](./references/docs/framework/vue/reactivity.md#keeping-queries-reactive) |
| 32 | |
| 33 | - Accept `MaybeRefOrGetter<T>` in composable parameters instead of string values — this allows callers to pass refs, plain values, or reactive getters (`() => props.userId`) without wrapper code, giving maximum flexibility [source](./references/docs/framework/vue/reactivity.md#using-derived-state-inside-queries) |
| 34 | |
| 35 | - Use `computed(() => props.property)` for derived state from component props, not direct property access — property access on reactive objects loses reactivity, but computed captures it in the query's reactive tracking [source](./references/docs/framework/vue/reactivity.md#using-derived-state-inside-queries) |
| 36 | |
| 37 | - Include all external variables used in `queryFn` in the `queryKey` — treat the query key like a dependency array; missing dependencies cause stale data and prevent proper cache invalidation [source](./references/docs/eslint/exhaustive-deps.md) |
| 38 | |
| 39 | - Create a single `QueryClient` instance at app initialization, not inside components — the client holds the cache for the entire app lifecycle, and recreating it loses all cached data [source](./references/docs/eslint/stable-query-cl |