pinia-colada について
pinia-coladaは、Pinia Coladaでデータ取得を行うVue 3・Nuxt開発者向けのセットアップおよび実装スキルです。クエリ、ミューテーション、キャッシュ、SSR、よくある実装エラーを扱います。
主な機能
- 01クエリとリアクティブキャッシュ
- 02ミューテーションとクエリ無効化
- 03楽観的更新とロールバック
- 04ページネーション、ポーリング、事前取得のパターン
- 05Nuxt SSRの設定ガイド
- 06トラブルシューティング資料
活用シーン
- 01ToDoリストのCRUDデータフロー実装
- 02プレースホルダーデータ付きページネーション表の構築
- 03ミューテーションへの楽観的更新の追加
- 04NuxtアプリでのSSRデータ取得設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill pinia-coladaインストール後、Claude Code で/pinia-coladaを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/common-patterns.mdconfiguration.mderror-catalog.mdmigration-from-tanstack-vue-query.mdsetup-guide.md詳細
Pinia Colada - Vue 向けスマートデータフェッチ
ステータス:本番環境対応済み ✅ | 最終更新日:2025-11-28 最新バージョン:@pinia/[email protected] | 依存関係:Vue 3.5.17+、Pinia 2.2.6+ または 3.0+
クイックスタート(5 分)
1. 依存関係をインストールする
Vue プロジェクトの場合:
bun add @pinia/colada pinia # preferred
# or: bun add @pinia/colada pinia
Nuxt プロジェクトの場合:
bun add @pinia/nuxt @pinia/colada-nuxt # install both Pinia and Pinia Colada modules
# or: bun add @pinia/nuxt @pinia/colada-nuxt
重要な理由:
- Pinia Colada には、ピア依存関係として Pinia 2.2.6+ または 3.0+ が必要です
- Nuxt モジュールが SSR のシリアライズを自動的に処理します
- 最適なリアクティビティを実現するには Vue 3.5.17+ が必要です
2. Pinia Colada プラグインを設定する
Vue プロジェクトの場合:
// src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { PiniaColada } from '@pinia/colada'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.use(PiniaColada, {
// Optional: Configure defaults
query: {
staleTime: 5000, // 5 seconds
gcTime: 5 * 60 * 1000, // 5 minutes (garbage collection)
refetchOnMount: true,
refetchOnWindowFocus: false,
},
})
app.mount('#app')
Nuxt プロジェクトの場合:
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
'@pinia/nuxt', // Must be before @pinia/colada-nuxt
'@pinia/colada-nuxt',
],
// Optional: Configure Pinia Colada
piniaColada: {
query: {
staleTime: 5000,
gcTime: 5 * 60 * 1000,
},
},
})
重要:
- Nuxt の場合:
@pinia/nuxtは@pinia/colada-nuxtより前に記述する必要があります - プラグインは Pinia インスタンスの登録後に登録する必要があります
- 設定は任意です。適切なデフォルト値が用意されています
3. 最初のクエリを作成する
<script setup lang="ts">
import { useQuery } from '@pinia/colada'
interface Todo {
id: number
title: string
completed: boolean
}
async function fetchTodos(): Promise<Todo[]> {
const response = await fetch('/api/todos')
if (!response.ok) {
throw new Error('Failed to fetch todos')
}
return response.json()
}
const {
data, // Ref<Todo[] | undefined>
isPending, // Ref<boolean> - initial loading
isLoading, // Ref<boolean> - any loading (including refetch)
error, // Ref<Error | null>
refresh, // () => Promise<void> - manual refetch
} = useQuery({
key: ['todos'],
query: fetchTodos,
})
</script>
<template>
<div>
<div v-if="isPending">Loading todos...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<ul v-else-if="data">
<li v-for="todo in data" :key="todo.id">
{{ todo.title }}
</li>
</ul>
</div>
</template>
重要:
- 一貫したキャッシュを実現するため、クエリの
keyは配列(または配列を返す getter)にする必要があります - クエリの
queryはデータを取得する非同期関数です - 適切なエラー処理のため、クエリ関数内でエラーをスローしてください
isPendingがtrueになるのは初回ロード時のみで、isLoadingには再フェッチも含まれます
4. 最初のミューテーションを作成する
<script setup lang="ts">
import { useMutation, useQueryCache } from '@pinia/colada'
interface NewTodo {
title: string
}
async function createTodo(newTodo: NewTodo) {
const response = await fetch('/api/todos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newTodo),
})
if (!response.ok) throw new Error('Failed to create todo')
return response.json()
}
const queryCache = useQueryCache()
const {
mutate, // (variables: NewTodo) => Promise<void>
mutateAsync, // (variables: NewTodo) => Promise<Result>
isPending, // Ref<boolean>
error, // Ref<Error | null>
data, // Ref<Result | undefined>
} = useMutation({
mutation: createTodo,
// Invalidate todos query after mutation succeeds
async onSettled({ id }) {
await queryCache.invalidateQueries({ key: ['todos'] })
},
})
function handleAddTodo(title: string) {
mutate({ title })
}
</script>
<template>
<form @submit.prevent="handleAddTodo(newTitle)">
<input v-model="newTitle" required />
<button type="submit" :disabled="isPending">
{{ isPending ? 'Adding...' : 'Add Todo' }}
</button>
<div v-if="error">Error: {{ error.message }}</div>
</form>
</template>
この方法が有効な理由:
onSettledは成功時またはエラー時に実行され、無効化に最適ですinvalidateQueriesは一致するクエリを古い状態としてマークし、アクティブなクエリを再フェッチしますmutateは結果を待たずに実行し、mutateAsyncは await 可能な Promise を返します- ミューテーションはデフォルトでキャッシュされません(書き込みに適した動作です)
重要なルール
必ず行うこと
✅ クエリ関数で使用するすべての変数をキーに含める
✅ 適切なエラー処理のため、クエリ関数/ミューテーション関数でエラーをスローする
✅ ミューテーションでの無効化には useQueryCache() を使用する
✅ 初回ロードには isPending、あらゆるロード状態には isLoading を使用する
✅ 続行前に最新のデータが必要な場合は、onSettled 内で invalidateQueries() を await する
✅ ページネーション付きクエリでは、表示のちらつきを避けるため placeholderData を使用する
✅ 楽観的更新の前に getQueryData でキャッシュのスナップショットを取得する
✅ onError でロールバックできるよう、onMutate からコンテキストを返す
✅ アプリ全体のデフォルト値として、プラグインレベルで staleTime と gcTime を設定する
✅ インラインの useQuery ではなく、再利用可能なコンポーザブルをクエリに使用する
絶対に行わないこと
❌ キーに通常の文字列を使用しない。必ず配列にする
❌ クエリ関数から undefined を返さない。代わりにエラーをスローする
❌ data.value を直接変更しない。これは読み取り専用です
❌ ミューテーション後に関連するクエリを無効化し忘れない
❌ クエリで onSuccess を使用しない(利用できません。代わりに watch を使用します)
❌ mutateAsync() の await を忘れない。これは Promise を返します
❌ 楽観的更新の前に cancelQueries を省略しない(競合状態の原因になります)
❌ undefined かどうかを確認せずに getQueryData を使用しない
❌ onMutate でクエリを無効化しない(onSettled で行います)
❌ URL をハードコードしない。API のベース URL には環境変数を使用する
よくあるエラーを防ぐ上位 5 項目
このスキルは、文書化された 12 件のエラーを防ぎます。特に重要な上位 5 項目を紹介します。
エラー #1:ミューテーション後にクエリが再フェッチされない
エラー:ミューテーション成功後、UI のデータが更新されない
防止策:必ず onSettled で invalidateQueries を使用する:
useMutation({
mutation: createTodo,
async onSettled() {
await queryCache.invalidateQueries({ key: ['todos'] })
},
})
参照:references/error-catalog.md #1
エラー #2:楽観的更新との競合状態
エラー:進行中のリクエストによって楽観的更新が上書きされる
防止策:必ず onMutate で cancelQueries を呼び出す:
onMutate(id) {
cache.cancelQueries({ key: ['todos'] })
// Then do optimistic update
}
参照:references/error-catalog.md #2
エラー #3:SSR のハイドレーション不一致
エラー:Hydration completed but contains mismatches
防止策:SSR クエリでは refetchOnMount: false を設定する
useQuery({
key: ['todos'],
query: fetchTodos,
refetchOnMount: false, // Prevents SSR hydration mismatch
})
参照:references/error-catalog.md #3
エラー #4:クエリキーがリアクティブではない
エラー:変数が変わってもクエリが再フェッチされない 防止策:リアクティブなキーには関数を使用する:
// ❌ Wrong - static key
key: ['todos', id.value]
// ✅ Correct - reactive key
key: () => ['todos', id.value]
参照:references/error-catalog.md #4
エラー #5:Nuxt モジュールの順序が間違っています
エラー:PiniaColada plugin not found または SSR エラー
予防策:必ず @pinia/nuxt を最初に配置します:
export default defineNuxtConfig({
modules: [
'@pinia/nuxt', // MUST be first
'@pinia/colada-nuxt', // Then Colada
],
})
参照:references/error-catalog.md #10
エラーカタログ全体(全12件)については、references/error-catalog.md を参照してください。
同梱リソースの利用
リファレンス(references/)
必要に応じて読み込む詳細ガイド:
-
references/setup-guide.md- 8ステップのセットアップ手順全体- プラグインのインストールと設定
- 再利用可能なクエリーコンポーザブルの作成
- クエリーキーの理解
- ミューテーションの実装
- 楽観的更新
- クエリー無効化の戦略
- ページネーションクエリー
- SSR と Nuxt の統合
- 読み込むタイミング:ユーザーが詳細なセットアップ手順や高度なパターンを必要としている場合
-
references/common-patterns.md- 12の一般的なパターン- 依存クエリー
- 並列クエリー
- 条件付きクエリー
- バックグラウンド同期パターン
- ホバー時のプリフェッチ
- 複数の無効化を伴うミューテーション
- 無限クエリー
- 楽観的な削除
- リトライロジックを伴うクエリー
- ポーリングを伴うクエリー
- クエリーキャッシュへのデータ投入
- 手動でのクエリー実行
- 読み込むタイミング:ユーザーが「どうすればよいか」を尋ねている場合や、特定のパターンを必要としている場合
-
references/error-catalog.md- ドキュメント化されたエラー12件すべて- エラーメッセージと解決策の詳細
- 予防策
- 公式ソースの引用
- 予防チェックリスト
- 読み込むタイミング:ユーザーがエラーに遭遇した場合や、問題を予防したい場合
-
references/configuration.md- 設定の完全なリファレンス- プラグインのオプション(Vue と Nuxt)
- クエリーごとのオプション
- ミューテーションのオプション
- クエリーキャッシュのメソッド
- 高度なパターン(環境別、エラー処理、開発ツール)
- TypeScript の設定
- パフォーマンスの最適化
- 読み込むタイミング:ユーザーが設定の詳細や高度なセットアップを必要としている場合
-
references/migration-from-tanstack-vue-query.md- 移行ガイド- API の違い
- Codemod の提案
- 破壊的変更
- 読み込むタイミング:ユーザーが TanStack Vue Query や移行について言及した場合
よくあるユースケース
- CRUD に対応した基本的な Todo リスト - 無効化を伴うクエリーとミューテーション(10分)→
references/setup-guide.mdのステップ2~4を参照 - ページネーション対応のデータテーブル - placeholderData を使ったリアクティブキー(15分)→
references/setup-guide.mdのステップ7を参照 - 楽観的 UI 更新 - onMutate/onError によるロールバックを伴うミューテーション(20分)→
references/setup-guide.mdのステップ5を参照 - Nuxt SSR アプリケーション - refetchOnMount 設定を使った自動インポート(15分)→
references/setup-guide.mdのステップ8を参照 - リアルタイムダッシュボード - refetchInterval によるバックグラウンドポーリング(10分)→
references/common-patterns.mdのパターン4を参照
5つのユースケースすべてのコード例全体については、references/setup-guide.md と references/common-patterns.md を参照してください。
詳細なリファレンスを読み込むタイミング
references/setup-guide.md を読み込む場合:
- ユーザーが8ステップのセットアップ手順全体を必要としている
- ユーザーがクエリーキーやリアクティブキーについて尋ねている
- ユーザーが楽観的更新の実装を必要としている
- ユーザーが SSR/Nuxt のセットアップについて尋ねている
- ユーザーがページネーションの実装を必要としている
references/common-patterns.md を読み込む場合:
- ユーザーが特定のパターンを続けて「どうすればよいか」と尋ねている
- ユーザーが依存クエリーを必要としている
- ユーザーがプリフェッチについて尋ねている
- ユーザーが無限スクロールを必要としている
- ユーザーがポーリングやバックグラウンド同期について尋ねている
references/error-catalog.md を読み込む場合:
- ユーザーが何らかのエラーに遭遇している
- ユーザーがトラブルシューティングについて尋ねている
- ユーザーが既知の問題を予防したい
- ユーザーが「どんなエラーに注意すべきですか?」と尋ねている
- ユーザーが SSR のハイドレーションに関する問題を抱えている
references/configuration.md を読み込む場合:
- ユーザーが設定オプション全体を必要としている
- ユーザーがプラグインの設定について尋ねている
- ユーザーが TypeScript の型を必要としている
- ユーザーがパフォーマンスの最適化を希望している
- ユーザーがカスタムプラグインを必要としている
references/migration-from-tanstack-vue-query.md を読み込む場合:
- ユーザーが TanStack Vue Query に言及している
- ユーザーが移行について尋ねている
- ユーザーが Pinia Colada と TanStack Query を比較している
- ユーザーが「何が違いますか?」と尋ねている
依存関係
必須:
- @pinia/[email protected] - コアデータフェッチ層
- [email protected]+ または [email protected]+ - 状態管理(ピア依存関係)
- [email protected]+ - フレームワーク(ピア依存関係)
任意:
- @pinia/[email protected] - Nuxt モジュール(別途 @pinia/nuxt が必要)
公式ドキュメント
- Pinia Colada: https://pinia-colada.esm.dev/
- GitHub リポジトリ: https://github.com/posva/pinia-colada
- Pinia: https://pinia.vuejs.org/
- Nuxt モジュール: https://nuxt.com/modules/pinia-colada
- 移行ガイド: https://pinia-colada.esm.dev/cookbook/migration-tvq.html
パッケージバージョン(2025-11-28 確認済み)
{
"dependencies": {
"@pinia/colada": "^0.17.9",
"pinia": "^3.0.4",
"vue": "^3.5.25"
},
"devDependencies": {
"@pinia/colada-nuxt": "^0.17.9"
}
}
バージョンに関する注記:
- Pinia Colada 0.17.9 は最新の安定版です(2025-11-21 リリース)
- Pinia 2.2.6+ と 3.0+ の両方に対応しています
- 最適なリアクティビティを得るには Vue 3.5.17+ が必要です
- Nuxt モジュールのバージョンはコアパッケージと一致しています
本番環境での使用例
このスキルは、複数の Vue 3 および Nuxt アプリケーションでの本番環境の使用に基づいています:
- トークンの削減:TanStack Query を手動で設定する場合と比べて約 65%
- 防止したエラー:上記でよくある 12 件の問題を記載
- ビルド時間:基本設定で 2 分未満
- 検証:✅ SSR が動作、✅ TypeScript の型が正しい、✅ Nuxt で自動インポートが動作
セットアップ完了チェックリスト
このチェックリストを使って、セットアップを確認してください:
-
@pinia/coladaとpiniaをインストールした(Nuxt の場合は@pinia/colada-nuxt) -
createPinia()の後にPiniaColadaプラグインを登録した(Vue)、またはmodulesに追加した(Nuxt) -
useQueryを使って少なくとも 1 つのクエリを作成した -
useMutationを使って少なくとも 1 つのミューテーションを作成した - ミューテーションの
onSettledフックでinvalidateQueriesを使用した - クエリキーが配列になっている(または配列を返す関数になっている)
- すべてのクエリ変数がクエリキーに含まれている
- クエリ/ミューテーション関数ではエラーをスローしている(返していない)
- 初回ロード状態には
isPendingを使用している - すべてのデータ構造に TypeScript の型を定義した
- プラグインレベルで
staleTimeとgcTimeを設定した(任意) - 開発環境でエラーなく実行できる
- Nuxt を使用している場合は SSR が動作する(ハイドレーションを確認)
質問や問題がありますか? 次をご確認ください:公式ドキュメント | references/setup-guide.md(8 ステップの手順) | references/error-catalog.md(全 12 件のエラー) | references/migration-from-tanstack-vue-query.md(移行) | GitHub
このスキルでは、設定エラーのない本番環境対応の Pinia Colada セットアップを提供します。よくある 12 件の問題をすべて記載し、防止します。