これは何か
TOOLS BOX 本体に組み込んだ画面ではありません。別リポジトリで動かす外部 Playground です。
Zustand・React Hook Form・Zod の組み合わせを実際に触って理解するための実験場です。壊して試すための環境として、TOOLS BOX 本体とは意図的に分けています。
GitHub リポジトリは現在準備中(private)です。動作確認は外部デモから行えます。
何を学べるか
この Playground では以下を動作確認できます。
createで store を定義する- selector による購読で再レンダリングを最小化する
set/getで状態を更新・参照するgetState()と subscribe の違いを確かめるsubscribe/subscribeWithSelectorで外部変更を検知するunsubscribeで購読を解除・管理するdevtoolsmiddleware で Redux DevTools と連携する- 各 store を初期値に リセット して挙動を再現する
- Zod schema・バリデーション・
coerceで入力を正規化する - React Hook Form の
watchで入力をリアルタイムに store へ反映する storeSyncで複数 store 間の状態を自動同期する- selector で取り出した action を コンポーネント間で受け渡す
画面構成
┌──────────────────────────────────┬─────────────────┐
│ タブ切り替えエリア │ Store Monitor │
│ ┌────────────────────────────┐ │ (常時表示) │
│ │ フォーム / 詳細 / 結果表示 │ │ │
│ └────────────────────────────┘ │ settingsStore │
│ │ profileStore │
│ [全ストアをリセット] │ uiStore │
│ │ detailStore │
└──────────────────────────────────┴─────────────────┘
| タブ | 内容 |
|---|---|
| フォーム | 設定入力。入力と同時にストアへリアルタイム反映 |
| 詳細 | mode / 推奨レートの操作。別ストアへの書き戻し例 |
| 結果表示 | 全ストアの確定値をまとめて表示 |
| Store Monitor | 右サイドに常時表示。全ストアをリアルタイム監視 |
ストア構成
| store | 役割 |
|---|---|
settingsStore | フォーム入力値(Zod 正規化済み)を保持。同期の起点 |
profileStore | 表示用に整形したプロフィール値(settingsStore から同期) |
detailStore | 詳細画面用の派生状態(suggestedRate など) |
uiStore | アクティブなタブ(表示制御のみ) |
データの流れ
フォーム入力(キー入力)
↓
React Hook Form (watch) でリアルタイム検知
↓
patchFormData で settingsStore を即時更新
↓
storeSync (subscribe) が変更を検知
↓
profileStore / detailStore へ自動同期
↓
selector で各 UI を再描画
↓
保存ボタン押下時: Zod parse → setFormData で確定値を保存
Zustand API の使い分け
| 場所 | 使うもの | 目的 |
|---|---|---|
| Store 内部 | set, get | 状態更新・現在値参照 |
| React component | useStore(selector) | 値の購読・再描画 |
| React 外 | store.getState() | 現在値取得(再描画なし) |
| store 同期層 | subscribe() | 変更監視 |
| 終了処理 | unsubscribe() | 購読解除 |
注意点
getState()は現在値を読むだけで React の再描画を発生させません。UI で値を表示する場合は selector を使いますpatchFormDataは Zod を通らないため、呼び出し側で値の正規化・クランプが必要ですsubscribeWithSelectorの shallow 比較により、関係ないフィールドの変更では同期が走りません
触り方
リポジトリをクローンしてローカルで起動できます。
npm install
npm run dev
起動後、以下の URL でデモ画面が開きます。
http://localhost:3000/zustand-demo
TOOLS BOX 本体と分ける理由
Playground は壊して試す場所です。TOOLS BOX 本体は整理された教材・完成例の場所です。
zustand_test は Next.js・React・MUI のバージョン構成が TOOLS BOX 本体とは異なります。そのまま取り込むと依存関係や UI 方針が重くなるため、現時点では外部 Demo として分けて運用します。
将来的な組み込み案
| フェーズ | 内容 |
|---|---|
| Phase A | 外部 Demo Build として掲載(現在の状態) |
| Phase B | Vercel 等にデプロイし、外部デモ URL を設定する |
| Phase C | TOOLS BOX 本体に Tailwind UI として /playgrounds/zustand-demo を移植する |
| Phase D | Zustand Playground の作り方を Playbook として整理する(完了) |