$npx -y skills add skilld-dev/vue-ecosystem-skills --skill pinia-colada-skilldThe smart data fetching layer for Vue.js. ALWAYS use when writing code importing \"@pinia/colada\". Consult for debugging, best practices, or modifying @pinia/colada, pinia/colada, pinia colada, pinia-colada.
| 1 | # posva/pinia-colada `@pinia/colada@1.2.1` |
| 2 | **Tags:** latest: 1.2.1 |
| 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: `useInfiniteQuery()` — v0.20.0 refactored: removed `merge`, changed `data` to `{ pages, pageParams }`, `initialPage` → `initialPageParam`, `loadMore` → `loadNextPage`, and `getNextPageParam` is now required (experimental) [source](./references/releases/CHANGELOG.md) |
| 10 | |
| 11 | - BREAKING: `PiniaColada` installation — v0.14.0 moved global options to `queryOptions: { ... }` and requires an options object for typing: `app.use(PiniaColada, {})` [source](./references/releases/CHANGELOG.md) |
| 12 | |
| 13 | - BREAKING: `useQuery()` aliases — `isFetching` was renamed to `isLoading` in v0.8.0 to better reflect its connection to `asyncStatus` [source](./references/releases/CHANGELOG.md) |
| 14 | |
| 15 | - BREAKING: Status split — v0.8.0 split `status` into `status` (data: `'pending'|'success'|'error'`) and `asyncStatus` (operation: `'idle'|'loading'`) [source](./references/releases/CHANGELOG.md) |
| 16 | |
| 17 | - BREAKING: Mutation IDs — v0.19.0 simplified mutation IDs to incremented numbers (starting at 1). `mutationCache.get()` now takes the ID, and `$n` suffix is removed from keys [source](./references/releases/CHANGELOG.md) |
| 18 | |
| 19 | - BREAKING: Cache Key structure — v0.16.0 refactored internal cache to support deeply nested objects for keys. `toCacheKey` now returns a plain string. Stricter types disallow `undefined` in keys [source](./references/releases/CHANGELOG.md) |
| 20 | |
| 21 | - BREAKING: `queryCache` method renames — `cancelQuery()` was renamed to `cancel()` in v0.11.0, and `cancelQueries()` was added for multiple cancellations [source](./references/releases/CHANGELOG.md) |
| 22 | |
| 23 | - BREAKING: `setQueryState` → `setEntryState` — v0.9.0 renamed this `queryCache` action to better match its purpose [source](./references/releases/CHANGELOG.md) |
| 24 | |
| 25 | - BREAKING: External `AbortError` — v0.18.0 now surfaces external abort signals as actual errors instead of silently ignoring them [source](./references/releases/CHANGELOG.md) |
| 26 | |
| 27 | - BREAKING: `placeholderData` types — v0.13.0 changed `placeholderData` to only allow returning `undefined` (not `null`) to improve type inference [source](./references/releases/CHANGELOG.md) |
| 28 | |
| 29 | - BREAKING: Devtools dependency — v0.21.0 removed built-in `@vue/devtools-api` dependency; use `@pinia/colada-devtools` instead [source](./references/releases/CHANGELOG.md) |
| 30 | |
| 31 | - NEW: `useInfiniteQuery()` — v0.13.5 introduced infinite scrolling support (experimental) [source](./references/releases/CHANGELOG.md) |
| 32 | |
| 33 | - NEW: `useQueryState()` — v0.17.0 added this for easier state management without the full `useQuery` return object [source](./references/releases/CHANGELOG.md) |
| 34 | |
| 35 | - NEW: Global Query Hooks — v0.8.0 introduced `PiniaColadaQueryHooksPlugin` to manage `onSuccess`, `onError`, and `onSettled` [source](./references/releases/CHANGELOG.md) |
| 36 | |
| 37 | **Also changed:** `serializeTreeMap` replaces `serialize` v0.14.0 · `transformError` removed v0.12.0 · `EntryKey` replaces `EntryNodeKey` v0.17.0 · `TResult` renamed `TData` v0.16.0 · `QueryPlugin` → `PiniaColada` v0.8.0 · `delayLoadingRef` removed v0.12.0 · `invalidateKeys` moved to plugin v0.10.0 |
| 38 | |
| 39 | ## Best Practices |
| 40 | |
| 41 | - Use the grouped `state` object for type-safe narrowing in templates — TypeScript cannot narrow destructured `data` or `error` refs based on the `status` ref due to Vue's `Ref` wrapper limitations [source](./references/docs/guide/queries.md) |
| 42 | |
| 43 | ```vue |
| 44 | <script setup lang="ts"> |
| 45 | const { state } = useQuery({ key: ['user'], query: fetchUser }) |
| 46 | </script> |
| 47 | |
| 48 | <template> |
| 49 | <div v-if="state.status === 'success'">{{ state.data.name }}</div> |
| 50 | <div v-else-if="state.status === 'error'">{{ state.error.message }}</div> |
| 51 | </template> |
| 52 | ``` |
| 53 | |
| 54 | - Wrap shared reactive state in `defineQuery()` to prevent desynchronization — regular composables recreate refs for each component instance, causing only the first component to successfully trigger key-based reactivity [source](./references/docs/advanced/reusable-queries.md) |
| 55 | |
| 56 | ```ts |
| 57 | export const useFilteredTodos = defineQuery(() => { |
| 58 | const search = ref('') |
| 59 | const query = useQuery({ |
| 60 | key: () => ['todos', { search: search.value }], |
| 61 | query: () => fetchTodos(search.value), |
| 62 | }) |
| 63 | return { ...query, search } |
| 64 | }) |
| 65 | ``` |
| 66 | |
| 67 | - Combine hierarchical key factories with `defineQueryOptions()` for strict type safety — this enables automatic type inference in `queryCache` methods without manual type casting or string-based key typos [source](./references/docs/guide/query-keys.md) |
| 68 | |
| 69 | ```ts |
| 70 | export const todoOptions = defineQueryOptions((id: string) => ({ |
| 71 | key: ['tod |