# 狀態管理系統文件
## 📋 概述
這個目錄包含了應用程式的狀態管理系統,採用 **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