zustand について
zustand は、React 向けの軽量なグローバル状態管理ツール、Zustand v5 のスキルです。React 開発者向けに、型付きストア、セレクター、組み合わせ可能なミドルウェア、大規模ストアのスライス構成を扱います。
主な機能
- 01型安全なグローバル状態ストア
- 02再レンダリングを抑えるアトミックセレクター
- 03persist と DevTools ミドルウェア
- 04Immer とセレクター購読ミドルウェア
- 05ドメイン別の状態スライス
活用シーン
- 01コンポーネント間でのクライアント状態共有
- 02ユーザー設定の永続化
- 03複数ドメインにまたがる状態の構成
- 04React 外での状態管理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ oakoss/ agent-skills --skill zustandインストール後、Claude Code で/zustandを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/middleware.mdmigration.mdslices-pattern.mdssr-hydration.mdstore-patterns.mdtesting.md詳細
Zustand の状態管理
概要
Zustand v5 は、useSyncExternalStore を基盤とする、React 向けの軽量なグローバル状態管理ライブラリです。React 18 以降が必要です(内部で useSyncExternalStore を使用します)。createWithEqualityFn を使う場合は、ピア依存関係として use-sync-external-store をインストールしてください。型安全なストア、再レンダリングを最小限に抑えるアトミックセレクター、合成可能なミドルウェア(persist、devtools、immer、subscribeWithSelector)、大規模アプリケーション向けのスライスパターンを提供します。クライアントのみで使うグローバル状態には Zustand を、サーバーから取得したデータには TanStack Query を使用してください。
使用する場面: クライアント側のグローバル状態、永続化するユーザー設定、複雑な複数ドメインのストア、コンポーネント間で共有する状態、バニラ(React 非依存)の状態管理。
使用しない場面: キャッシュが必要なサーバー状態(TanStack Query を使用)、単一コンポーネントの状態(useState を使用)、単純な props のバケツリレー。
クイックリファレンス
| パターン | API | 主なポイント |
|---|---|---|
| 基本的なストア | create<T>()((set) => ({...})) | TS では二重の括弧が必要です |
| アトミックセレクター | useStore(state => state.bears) | 選択した値が変化したときだけ再レンダリングします |
| 複数の値 | useShallow(state => ({a, b})) | zustand/react/shallow からインポートします |
| 永続化 | persist(fn, { name }) | SSR のハイドレーション処理を備えた localStorage |
| DevTools | devtools(fn, { name }) | Redux DevTools との統合 |
| SubscribeWithSelector | subscribeWithSelector(fn) | React の外部で状態のスライスを購読します |
| ミドルウェアの順序 | devtools(persist(fn)) | 外側から内側へラップします |
| スライスパターン | StateCreator<Combined, [], [], Slice> | ドメインごとにストアを分割します |
| SSR プロバイダー | createStore + React Context | リクエストごとのストアでデータ漏えいを防ぎます |
| Immer | immer(fn) | ネストされた状態を安全に変更します |
| バニラストア | zustand/vanilla の createStore | React の外部で使用します |
| ストアのリセット | set(store.getInitialState()) | 確実にリセットするには getInitialState() を使用します |
| 派生値 | useStore(s => s.items.length) | セレクター内で計算します |
| 自動セレクター | createSelectors(store) | store.use.field() フックを自動生成します |
よくある間違い
| 間違い | 正しいパターン |
|---|---|
create<T>(...) を単一の括弧で使う | TypeScript のミドルウェア推論を正しく行うには、二重の括弧を使って create<T>()(...) とします |
useStore(state => state) で状態オブジェクト全体を選択する | 不要な再レンダリングを避けるため、state.bears のようなアトミックセレクターや useShallow を使います |
useShallow を zustand/shallow からインポートする | zustand/react/shallow からインポートします。zustand/shallow がエクスポートするのは通常の shallow 関数のみです |
| セレクター内で新しいオブジェクト参照を作成し、無限ループを引き起こす | プリミティブ値を個別のセレクターで選択するか、zustand/react/shallow の useShallow でラップします |
| SSR や Next.js でグローバルなシングルトンストアを使う | リクエスト間のデータ漏えいを防ぐため、createStore を使った StoreContext プロバイダーパターンを使います |
| リセット用の初期状態を手動で追跡する | Zustand が自動的に提供する store.getInitialState() を使います |
| キャッシュと再検証が必要なサーバー取得データに Zustand を使う | サーバー状態には TanStack Query を使い、Zustand はクライアント専用のグローバル状態に使用します |
委任
- ストアのアーキテクチャとスライスの設計:
Planエージェントを使って、ドメインの境界、スライスのインターフェース、ミドルウェアの合成順序を定義します - ハイドレーションと SSR のデバッグ:
Taskエージェントを使って、persist ミドルウェアの問題、ハイドレーションの不一致、Next.js のプロバイダー設定を診断します - v4 から v5 への移行:
Exploreエージェントを使って、非推奨のインポートパス、単一括弧のパターン、旧式のミドルウェアの使用箇所を見つけます - テスト戦略:
Taskエージェントを使って、ストアのモックとテストの分離パターンを設定します