状態管理アーキテクチャ¶
React Context API + useReducerを採用
日付: 2025-01-06
ステータス¶
~~2025-01-06 承認済み~~
2025-08-09 非推奨 → 007-依存性注入とアーキテクチャリファクタリング.md で置換
コンテキスト¶
ぷよぷよゲームでは以下の状態管理が必要:
- ゲーム状態(プレイ中、ポーズ、ゲームオーバー)
- フィールドの状態(ぷよの配置)
- スコア、連鎖数、レベル
- 現在の操作中ぷよペア
- NEXTキュー
候補として以下を検討:
- React Context API + useReducer
- Redux Toolkit
- Zustand
- Jotai
- ローカル状態のみ(useState)
決定¶
React Context API + useReducer を採用する
理由¶
Context API:
- Reactの標準機能で追加の依存関係不要
- 小〜中規模アプリケーションに適している
- TypeScriptとの統合が容易
- パフォーマンス問題は適切な設計で回避可能
useReducer:
- Reduxライクな予測可能な状態更新
- 複雑な状態変更ロジックを整理
- 時間旅行デバッグに対応
- アクションベースの設計でテストが容易
他の選択肢を除外した理由:
- Redux: 小規模アプリには過剰な複雑さ
- Zustand/Jotai: 学習コストと将来の保守性への懸念
- ローカル状態のみ: コンポーネント間の状態共有が困難
影響¶
ポジティブな影響¶
- シンプルさ: 外部依存なしで状態管理
- 型安全性: TypeScriptとの完全な統合
- テスタビリティ: Reducerの単体テストが容易
- デバッグ性: React DevToolsでの状態追跡
ネガティブな影響¶
- パフォーマンス: 不適切な設計時の不要な再レンダリング
- ボイラープレート: アクション・リデューサーの定義が必要
- スケーラビリティ: 大規模になった場合の複雑さ
軽減策¶
- Context の適切な分割(ゲーム状態、UI状態)
- useMemoとuseCallbackによる最適化
- カスタムフックによるロジックの抽象化
アーキテクチャ詳細¶
Context 構成¶
// ゲーム状態用Context
const GameContext = createContext<GameState>();
// UI状態用Context
const UIContext = createContext<UIState>();
Reducer パターン¶
type GameAction =
| { type: 'START_GAME' }
| { type: 'MOVE_PUYO'; direction: Direction }
| { type: 'ROTATE_PUYO' }
| { type: 'DROP_PUYO' };
function gameReducer(state: GameState, action: GameAction): GameState {
switch (action.type) {
case 'START_GAME':
return initializeGame();
// ...
}
}
カスタムフック¶
export function useGame() {
const context = useContext(GameContext);
if (!context) {
throw new Error('useGame must be used within GameProvider');
}
return context;
}
コンプライアンス¶
この決定の遵守は以下により確認:
- Context Provider の適切な配置
- useReducer の使用
- カスタムフックによる状態アクセス
- TypeScript による型定義の存在
備考¶
- 決定者: 開発チーム
- 影響範囲: 状態管理全体
- レビュー予定: プロトタイプ完成後またはパフォーマンス問題発生時