dramaling-vocab-learning/frontend/store/README.md

334 lines
8.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 狀態管理系統文件
## 📋 概述
這個目錄包含了應用程式的狀態管理系統,採用 **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 <ErrorComponent message={error} />
}
if (isLoading) {
return <LoadingComponent />
}
```
## 🧪 測試策略
### 單元測試
```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<ReviewSessionState>()(
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