# 狀態管理系統文件 ## 📋 概述 這個目錄包含了應用程式的狀態管理系統,採用 **Zustand** 作為狀態管理工具。系統被設計為模組化架構,將原本單一巨大的 store 拆分為多個專門化的 stores,每個都有明確的職責範圍。 ## 🏗️ 架構設計 ### 設計原則 - **單一職責原則**: 每個 store 只負責特定的狀態域 - **最小重渲染**: 組件只訂閱需要的狀態,避免不必要的重渲染 - **型別安全**: 使用 TypeScript 確保型別安全 - **可測試性**: 小型、專注的 stores 更容易測試 ### Store 分類 (按功能模組組織) ``` /store/ ├── review/ # 複習功能相關 Store │ ├── useReviewSessionStore.ts # 會話狀態管理 │ ├── useTestQueueStore.ts # 測試隊列管理 │ ├── useTestResultStore.ts # 測試結果管理 │ ├── useReviewDataStore.ts # 數據狀態管理 │ └── useReviewUIStore.ts # Review UI 狀態管理 └── README.md # 架構說明文檔 ``` ## 📚 各 Store 詳細說明 ### 1. useReviewSessionStore.ts **職責**: 管理複習會話的核心狀態 #### 狀態內容 ```typescript interface ReviewSessionState { // 核心會話狀態 mounted: boolean // 組件是否已掛載 isLoading: boolean // 是否正在載入 error: string | null // 錯誤訊息 // 當前卡片狀態 currentCard: ExtendedFlashcard | null // 當前顯示的詞卡 currentCardIndex: number // 當前卡片索引 } ``` #### 主要功能 - **會話生命週期管理**: 控制會話的開始、結束 - **當前卡片追蹤**: 追蹤使用者正在學習的詞卡 - **錯誤處理**: 統一管理會話相關錯誤 #### 使用範例 ```typescript const { currentCard, error, setCurrentCard } = useReviewSessionStore() // 設置當前卡片 setCurrentCard(newCard) ``` --- ### 2. useTestQueueStore.ts **職責**: 管理測試隊列和測試流程 #### 狀態內容 ```typescript interface TestQueueState { testItems: TestItem[] // 測試項目清單 currentTestIndex: number // 當前測試索引 completedTests: number // 已完成測試數量 totalTests: number // 總測試數量 currentMode: ReviewMode // 當前測試模式 } ``` #### 主要功能 - **測試隊列初始化**: 根據詞卡和已完成測試建立隊列 - **測試進度管理**: 追蹤測試進度和完成狀態 - **測試流程控制**: 控制測試的前進、跳過等操作 #### 核心方法 ```typescript // 初始化測試隊列 initializeTestQueue(dueCards, completedTests) // 進入下一個測試 goToNextTest() // 跳過當前測試 skipCurrentTest() // 標記測試完成 markTestCompleted(testIndex) ``` #### 測試類型 - `flip-memory`: 翻卡記憶 - `vocab-choice`: 詞彙選擇 - `vocab-listening`: 詞彙聽力 - `sentence-listening`: 例句聽力 - `sentence-fill`: 例句填空 - `sentence-reorder`: 例句重組 - `sentence-speaking`: 例句口說 --- ### 3. useTestResultStore.ts **職責**: 管理測試結果和分數統計 #### 狀態內容 ```typescript interface TestResultState { score: { correct: number; total: number } // 分數統計 isRecordingResult: boolean // 是否正在記錄結果 recordingError: string | null // 記錄錯誤 } ``` #### 主要功能 - **分數追蹤**: 記錄正確和總答題數 - **結果記錄**: 將測試結果發送到後端 - **統計計算**: 提供準確率等統計資訊 #### 核心方法 ```typescript // 更新分數 updateScore(isCorrect: boolean) // 記錄測試結果到後端 recordTestResult({ flashcardId, testType, isCorrect, userAnswer, confidenceLevel, responseTimeMs }) // 獲取準確率 getAccuracyPercentage() ``` --- ### 4. useReviewDataStore.ts **職責**: 管理複習數據和UI顯示狀態 #### 狀態內容 ```typescript interface ReviewDataState { dueCards: ExtendedFlashcard[] // 到期詞卡清單 showComplete: boolean // 是否顯示完成畫面 showNoDueCards: boolean // 是否顯示無詞卡畫面 isLoadingCards: boolean // 是否正在載入詞卡 loadingError: string | null // 載入錯誤 } ``` #### 主要功能 - **詞卡資料管理**: 載入和管理到期的詞卡 - **UI 狀態控制**: 控制不同UI狀態的顯示 - **資料快取**: 快取詞卡資料避免重複請求 #### 核心方法 ```typescript // 載入到期詞卡 loadDueCards() // 根據ID查找詞卡 findCardById(cardId) // 獲取詞卡數量 getDueCardsCount() ``` --- ### 5. useUIStore.ts **職責**: 管理全域UI狀態 #### 狀態內容 ```typescript interface UIState { showTaskListModal: boolean // 任務清單Modal showReportModal: boolean // 錯誤回報Modal modalImage: string | null // 圖片Modal reportReason: string // 回報原因 reportingCard: any | null // 正在回報的詞卡 isAutoSelecting: boolean // 自動選擇狀態 } ``` ## 🔄 Store 之間的協作 ### 資料流向 ```mermaid graph TD A[useReviewDataStore] -->|詞卡資料| B[useTestQueueStore] B -->|當前測試| C[useReviewSessionStore] C -->|測試互動| D[useTestResultStore] D -->|結果回饋| B E[useUIStore] -.->|UI狀態| A E -.->|UI狀態| B E -.->|UI狀態| C E -.->|UI狀態| D ``` ### 協作流程 1. **初始化階段**: - `useReviewDataStore` 載入到期詞卡 - `useTestQueueStore` 根據詞卡建立測試隊列 - `useReviewSessionStore` 設置當前詞卡 2. **測試階段**: - `useReviewSessionStore` 管理當前測試狀態 - `useTestResultStore` 記錄測試結果 - `useTestQueueStore` 控制測試進度 3. **完成階段**: - `useTestQueueStore` 檢查是否完成所有測試 - `useReviewDataStore` 顯示完成狀態 ## 🎯 使用最佳實踐 ### 1. 選擇性訂閱 ```typescript // ❌ 避免:訂閱整個 store const store = useReviewSessionStore() // ✅ 推薦:只訂閱需要的狀態 const { currentCard, error } = useReviewSessionStore() ``` ### 2. 狀態更新模式 ```typescript // ✅ 推薦:使用專門的 actions const { setCurrentCard } = useReviewSessionStore() setCurrentCard(newCard) // ❌ 避免:直接修改狀態 // store.currentCard = newCard // 這樣不會觸發重渲染 ``` ### 3. 錯誤處理 ```typescript // ✅ 推薦:檢查錯誤狀態 const { error, isLoading } = useReviewSessionStore() if (error) { return } if (isLoading) { return } ``` ## 🧪 測試策略 ### 單元測試 ```typescript // 測試 store 的 actions describe('useTestResultStore', () => { it('should update score correctly', () => { const { updateScore, score } = useTestResultStore.getState() updateScore(true) expect(score.correct).toBe(1) expect(score.total).toBe(1) }) }) ``` ### 整合測試 ```typescript // 測試多個 stores 的協作 describe('Review Flow Integration', () => { it('should coordinate between stores correctly', () => { // 測試資料載入 → 隊列建立 → 測試執行的流程 }) }) ``` ## 🔧 開發工具 ### Zustand DevTools ```typescript import { subscribeWithSelector, devtools } from 'zustand/middleware' export const useReviewSessionStore = create()( devtools( subscribeWithSelector((set, get) => ({ // store implementation })), { name: 'review-session-store' } ) ) ``` ## 📈 效能考量 ### 重渲染優化 - **狀態分離**: 不相關的狀態變更不會觸發組件重渲染 - **選擇性訂閱**: 組件只訂閱需要的狀態片段 - **記憶化**: 使用 `useMemo` 和 `useCallback` 優化計算 ### 記憶體管理 - **自動清理**: stores 會在適當時機重置狀態 - **垃圾回收**: 移除不再需要的資料引用 ## 🚀 未來擴展 ### 新增 Store 1. 建立新的 store 檔案 2. 定義 interface 和初始狀態 3. 實作 actions 和 getters 4. 加入適當的 TypeScript 型別 5. 更新文件 ### Store 拆分指導原則 - 當 store 超過 150 行時考慮拆分 - 根據業務邏輯邊界進行拆分 - 確保拆分後的 stores 職責清晰 --- ## 📞 支援 如有問題或需要協助,請參考: - [Zustand 官方文件](https://zustand-demo.pmnd.rs/) - [TypeScript 最佳實踐](https://www.typescriptlang.org/docs/) - 團隊內部技術文件 **維護者**: 開發團隊 **最後更新**: 2025-09-28