pinia-colada-skilld

The 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.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "pinia-colada-skilld" with this command: npx skills add harlan-zw/vue-ecosystem-skills/harlan-zw-vue-ecosystem-skills-pinia-colada-skilld

posva/pinia-colada @pinia/colada

The smart data fetching layer for Vue.js

Version: 1.0.0 (Mar 2026) Tags: latest: 1.0.0 (Mar 2026)

References: Docs — API reference, guides

API Changes

This section documents version-specific API changes — prioritize recent major/minor releases.

  • BREAKING: useInfiniteQuery() — v0.20.0 refactored: removed merge, changed data to { pages, pageParams }, initialPageinitialPageParam, loadMoreloadNextPage, and getNextPageParam is now required (experimental) source

  • BREAKING: PiniaColada installation — v0.14.0 moved global options to queryOptions: { ... } and requires an options object for typing: app.use(PiniaColada, {}) source

  • BREAKING: useQuery() aliases — isFetching was renamed to isLoading in v0.8.0 to better reflect its connection to asyncStatus source

  • BREAKING: Status split — v0.8.0 split status into status (data: 'pending'|'success'|'error') and asyncStatus (operation: 'idle'|'loading') source

  • 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

  • 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

  • BREAKING: queryCache method renames — cancelQuery() was renamed to cancel() in v0.11.0, and cancelQueries() was added for multiple cancellations source

  • BREAKING: setQueryStatesetEntryState — v0.9.0 renamed this queryCache action to better match its purpose source

  • BREAKING: External AbortError — v0.18.0 now surfaces external abort signals as actual errors instead of silently ignoring them source

  • BREAKING: placeholderData types — v0.13.0 changed placeholderData to only allow returning undefined (not null) to improve type inference source

  • BREAKING: Devtools dependency — v0.21.0 removed built-in @vue/devtools-api dependency; use @pinia/colada-devtools instead source

  • NEW: useInfiniteQuery() — v0.13.5 introduced infinite scrolling support (experimental) source

  • NEW: useQueryState() — v0.17.0 added this for easier state management without the full useQuery return object source

  • NEW: Global Query Hooks — v0.8.0 introduced PiniaColadaQueryHooksPlugin to manage onSuccess, onError, and onSettled source

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 · QueryPluginPiniaColada v0.8.0 · delayLoadingRef removed v0.12.0 · invalidateKeys moved to plugin v0.10.0

Best Practices

  • 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
<script setup lang="ts">
const { state } = useQuery({ key: ['user'], query: fetchUser })
</script>

<template>
  <div v-if="state.status === 'success'">{{ state.data.name }}</div>
  <div v-else-if="state.status === 'error'">{{ state.error.message }}</div>
</template>
  • 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
export const useFilteredTodos = defineQuery(() => {
  const search = ref('')
  const query = useQuery({
    key: () => ['todos', { search: search.value }],
    query: () => fetchTodos(search.value),
  })
  return { ...query, search }
})
  • 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
export const todoOptions = defineQueryOptions((id: string) => ({
  key: ['todos', id],
  query: () => fetchTodo(id),
}))
// Inferred TData: queryCache.getQueryData(todoOptions('1').key)
  • Handle side effects via watch or global plugins instead of query options — useQuery intentionally lacks onSuccess/onError to prevent side-effect duplication across multiple component instances source

  • Prefer refresh() over refetch() for standard UI updates — refresh() respects staleTime and deduplicates in-flight requests, whereas refetch() forces a network call regardless of cache status source

  • Use the meta property for declarative cross-cutting concerns — attach metadata to queries to drive global UI behavior (like toast messages) within the PiniaColadaQueryHooksPlugin source

  • Verify cache state before performing optimistic rollbacks — always check if the current cache value matches the optimistic value in onError to avoid overwriting concurrent successful updates from other mutations source

onError(err, vars, { newTodo, oldTodo }) {
  if (newTodo === queryCache.getQueryData(['todos'])) {
    queryCache.setQueryData(['todos'], oldTodo)
  }
}
  • Use queryCache.setEntryState() for manual status synchronization — this is the preferred way to manually update an entry as setting data to undefined via setQueryData() is no longer supported for state resets source

  • Explicitly import useRoute from vue-router in Nuxt defineQuery definitions — the Nuxt auto-imported version can cause unnecessary query triggers or undefined values due to Suspense integration source

  • Use the enabled getter to guard "immortal" queries in global stores — prevents queries inside Pinia stores from making invalid network requests when required reactive parameters (like route params) are absent source

const result = useQuery({
  key: () => ['deck', route.params.id],
  query: () => fetchDeck(route.params.id),
  enabled: () => !!route.params.id,
})

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

vue-skilld

No summary provided by upstream source.

Repository SourceNeeds Review
General

pinia-skilld

No summary provided by upstream source.

Repository SourceNeeds Review
General

vueuse-core-skilld

No summary provided by upstream source.

Repository SourceNeeds Review
General

vue-router-skilld

No summary provided by upstream source.

Repository SourceNeeds Review