tanstack-vue-store-skilld について
tanstack-vue-store-skilld は、Vue 向け TanStack Store アダプター @tanstack/vue-store の利用を案内するスキルです。Vue 開発者向けに、セレクターや atom のフックでコンポーネントとストアを接続し、コア API も同じパッケージから利用できます。
主な機能
- 01useSelector による Store や atom の読み取り
- 02useAtom による atom の読み書き
- 03_useStore による Store アクションの取得
- 04TanStack Store コア API の再エクスポート
- 05vue-demi 経由の Vue 2 と Vue 3 対応
活用シーン
- 01選択した Store の状態をコンポーネントで購読
- 02モジュール定義の Store を Vue コンポーネント間で共有
- 03複数の状態更新を一度の通知にまとめる
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ skilld-dev/ vue-ecosystem-skills --skill tanstack-vue-store-skilldインストール後、Claude Code で/tanstack-vue-store-skilldを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/core-api.mdmigration.mdpatterns.mdvue-hooks.md詳細
@tanstack/[email protected]
TanStack Store の Vue アダプターです。コアの依存関係は正確に @tanstack/[email protected] です(package.json:41)。src/index.ts:1 でコア全体を再エクスポートしているため、Vue アプリでは @tanstack/vue-store だけからすべてをインポートできます。
クイックスタート
import { createStore, createAtom, shallow, useAtom, useSelector } from '@tanstack/vue-store'
// Module scope: create once, import anywhere
const counter = createStore({ count: 0 })
const countAtom = createAtom(0)
// Inside <script setup>
const count = useSelector(counter, (s) => s.count) // slice
const pair = useSelector(counter, (s) => ({ n: s.count }), { compare: shallow }) // object slice
const [n, setN] = useAtom(countAtom) // read + write
setN((prev) => prev + 1)
テンプレートでは {{ count }}、スクリプトでは count.value として ref を読み取ります。
フック(このパッケージ独自のエクスポート)
| フック | シグネチャ | 用途 |
|---|---|---|
useSelector | (source, selector?, options?) => Readonly<Ref<TSelected>> | 主な読み取り用フックです。Store、atom、または { get, subscribe } を備えた任意のソースを使用できます。セレクターを省略すると、値全体をサブスクライブします。 |
useAtom | (atom, options?) => [Readonly<Ref<TValue>>, atom.set] | 書き込み可能な atom 1 つに対する読み取りと書き込みを行います。セッターには値またはアップデーター関数を渡します(src/useAtom.ts:20-27)。 |
_useStore | (store, selector, options?) => [selected, actions or setState] | 読み取りと書き込みを行う実験的なタプルです。セレクター引数は必須です(src/_useStore.ts:30)。ストアに actions ファクトリーがある場合は store.actions、ない場合は store.setState を返します(src/_useStore.ts:37-38)。 |
useStore | 非推奨 | useSelector のエイリアスです。第 3 引数はオプションオブジェクトではなく、単独の compare 関数です(src/useStore.ts:14-23)。useSelector を優先してください。 |
options は UseSelectorOptions です:{ compare?: (a, b) => boolean }(src/useSelector.ts:4-6)。
詳細、動作に関する注意点、落とし穴については、Vue フックリファレンスを参照してください。
バグを防ぐためのルール
- デフォルトの比較方法は厳密な
===です(src/useSelector.ts:15-17)。セレクターが新しいオブジェクトや配列を生成する場合は、{ compare: shallow }を渡してください。そうしないと、通知のたびに ref が更新されます。プリミティブ値を返すセレクターには、カスタム比較関数は不要です。 - フックは、コンポーネントの setup または別のエフェクトスコープ内で呼び出してください。
useSelectorはonScopeDisposeを使ってサブスクリプションを解除します(src/useSelector.ts:54-56)。スコープの外ではクリーンアップが実行されません。 - 返される ref は
readonlyです。書き込みにはstore.setState、atom.set、ストアのactions、またはuseAtom/_useStoreの第 2 タプル要素を使用してください。 - セレクターは低コストに保ってください。セレクターはソースの通知のたびに実行されます(
src/useSelector.ts:46-52)。コストの高い計算は派生createStoreに移してください。 - このパッケージから
createStoreContextをインポートしないでください。0.11.0 のリリースノートには記載されていますが、0.11.1 のソースがエクスポートするのはuseSelector、useAtom、useStore、_useStoreとコアの再エクスポートのみです(src/index.ts、dist/index.d.ts)。リリース 0.11.0を参照してください。
@tanstack/store からのコアの再エクスポート
createStore(initialValue)->Store<T>、createStore((prev?) => T)->ReadonlyStore<T>(派生型)、createStore(initialValue, actionsFactory)->Store<T, TActions>(型付きのstore.actionsを備えます)。Store:stateゲッター、get()、setState(updater)、{ unsubscribe }を返すsubscribe(observerOrFn)、バインドされたactions。ReadonlyStoreにはsetStateとactionsがありません。createAtom(initialValue)-> 書き込み可能なAtom<T>、createAtom(fn)-> 計算されたReadonlyAtom<T>。AtomOptions.compareは変更検知を制御します。createAsyncAtom(() => Promise<T>)->'pending' | 'done' | 'error'を判別可能なユニオンとする{ status }のReadonlyAtom。batch(fn)は更新を 1 回の通知サイクルにまとめます。flush()は保留中のエフェクトを処理します。shallow(a, b)はObject.is、Map と Set の内容、Date のタイムスタンプ、およびシンボルを含む独自キーを比較します。toObserver()はsubscribe用のコールバックまたは RxJS 形式のオブザーバーを正規化します。- 型:
Observer、Subscription、Subscribable、Readable、Atom、ReadonlyAtom、AtomOptions、StoreActionMap、StoreActionsFactoryなど。
注意点を含む全 API については、コア API リファレンスを参照してください。
ベストプラクティス
- 新しいコードでは、非推奨の
useStoreではなくuseSelectorを使用します(src/useSelector.ts:39)。 - コンポーネントの外部にあるプレーンなモジュールでストアを定義します。これはドキュメントで説明されている共有パターンです(Vue クイックスタート)。
- 細かく分割したスライスを選択します。選択した値が変わった場合にのみ、コンポーネントが再レンダリングされます。
store.setState((prev) => next)の更新関数を使って状態を変更します。更新はイミュータブルです。- 複数の更新を
batch(() => { ... })にまとめることで、購読者への通知を最終状態で一度だけ行います。 createStore(() => ...)で派生させます。派生ストアは依存関係が変わると再計算され、prevに値が蓄積されます。- 書き込み処理はアクションファクトリーと同じ場所にまとめ、
_useStoreが型付きアクションを返すようにします(src/_useStore.ts:37-38)。 - 非同期データには、手作業で保留中・エラーフラグを作成する代わりに
createAsyncAtomを使用します。 - コンポーネントの外部で状態を監視するには、
store.subscribe(() => ...)を使用します。戻り値は{ unsubscribe }です。
レシピと完全な例:パターンリファレンス
移行
バージョンごとの変更点とアップグレード手順を、最新のものから掲載しています:移行リファレンス
主な変更点:
- 0.11.x:主要なフックとして
useSelectorを導入し、useStoreを非推奨にしました。デフォルトの比較方法は===で、0.11 より前のデフォルトだったshallowおよび{ equal }オプションに代わります。 - 0.9.0 の破壊的変更:
new Store()はcreateStore()に、new Derived()は派生createStore(fn)に置き換わりました。new Effect()は削除され、store.subscribe()を使用するようになりました。
環境
- Vue
^3.0.0またはvue-demi経由の^2.5.0。Vue 2 では、オプションのピア依存関係@vue/composition-api@^1.2.1が必要です(package.json:50-58)。 - コアのバージョンは
@tanstack/[email protected]に厳密に固定されています。コア API は再エクスポートされるため、Vue アプリでコアを別途インストールする必要はありません。 - デュアル形式:
import条件では ESM(dist/index.js)、requireでは CJS(dist/index.cjs)を使用します。型定義はdist/index.d.ctsにあり、sideEffects: falseです。 - TypeScript 5.6 から 5.9 までをテスト済みです(package.json:62-66)。