|
|
@@ -1,124 +0,0 @@
|
|
|
-# 聊天页面架构修复说明
|
|
|
-
|
|
|
-## 🚨 发现的问题
|
|
|
-
|
|
|
-### 多实例问题 (Critical Issue)
|
|
|
-
|
|
|
-在重构过程中发现了一个严重的架构问题:`useChatInput` Hook 被多个组件同时使用,导致创建了多个独立实例:
|
|
|
-
|
|
|
-1. **InputBar/index.tsx** - 输入栏组件
|
|
|
-2. **RecommendQuestions/index.tsx** - 推荐问题组件
|
|
|
-3. **ChatGreeting/index.tsx** - 欢迎问候组件
|
|
|
-
|
|
|
-### 问题影响
|
|
|
-
|
|
|
-1. **重复副作用**: 每个实例都会执行相同的 `useEffect` 清理逻辑
|
|
|
-2. **状态管理冲突**: 多个实例操作同一个全局 `useTextChat` store
|
|
|
-3. **资源浪费**: 多个定时器、事件监听器同时运行
|
|
|
-4. **竞态条件**: 多个实例可能同时修改聊天状态,导致不可预测的行为
|
|
|
-
|
|
|
-## 🔧 解决方案: 状态提升 (State Lifting)
|
|
|
-
|
|
|
-### 修复策略
|
|
|
-
|
|
|
-采用 React 最佳实践中的"状态提升"模式:
|
|
|
-
|
|
|
-1. **单一实例**: 将 `useChatInput` 提升到聊天页面主组件中,确保只有一个实例
|
|
|
-2. **Props 传递**: 通过 props 将需要的方法传递给子组件
|
|
|
-3. **状态集中管理**: 在主组件中统一管理 InputBar 的状态(isVoice, disabled)
|
|
|
-
|
|
|
-### 修复前后对比
|
|
|
-
|
|
|
-#### 修复前 ❌
|
|
|
-```typescript
|
|
|
-// InputBar 组件
|
|
|
-const {handleBeforeSend, sendChatMessage} = useChatInput({agent, ...});
|
|
|
-
|
|
|
-// RecommendQuestions 组件
|
|
|
-const {sendChatMessage, setQuestions} = useChatInput({agent, ...});
|
|
|
-
|
|
|
-// ChatGreeting 组件
|
|
|
-const {sendChatMessage} = useChatInput({agent});
|
|
|
-```
|
|
|
-**问题**: 3个独立的 `useChatInput` 实例同时运行
|
|
|
-
|
|
|
-#### 修复后 ✅
|
|
|
-```typescript
|
|
|
-// 主组件 (chat/index.tsx)
|
|
|
-const chatInputActions = useChatInput({
|
|
|
- agent,
|
|
|
- enableOutputAudioStream: streamVoiceEnable,
|
|
|
- setShowWelcome,
|
|
|
- setIsVoice,
|
|
|
- setDisabled,
|
|
|
-});
|
|
|
-
|
|
|
-// 子组件通过 props 接收
|
|
|
-<InputBar chatInputActions={chatInputActions} />
|
|
|
-<RecommendQuestions chatInputActions={chatInputActions} />
|
|
|
-<ChatGreeting chatInputActions={chatInputActions} />
|
|
|
-```
|
|
|
-**优势**: 单一 `useChatInput` 实例,通过 props 共享
|
|
|
-
|
|
|
-### 架构改进
|
|
|
-
|
|
|
-```
|
|
|
-Before:
|
|
|
-┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
|
-│ InputBar │ │RecommendQuestions│ │ ChatGreeting │
|
|
|
-│ │ │ │ │ │
|
|
|
-│ useChatInput() │ │ useChatInput() │ │ useChatInput() │
|
|
|
-│ ↓ │ │ ↓ │ │ ↓ │
|
|
|
-│ [Instance 1] │ │ [Instance 2] │ │ [Instance 3] │
|
|
|
-└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
|
- ↓ ↓ ↓
|
|
|
- ┌─────────────────────────────────────────────────────────┐
|
|
|
- │ useTextChat (Global Store) │
|
|
|
- │ ⚠️ Conflicts! │
|
|
|
- └─────────────────────────────────────────────────────────┘
|
|
|
-
|
|
|
-After:
|
|
|
-┌─────────────────────────────────────────────────────────────┐
|
|
|
-│ Chat Page (Main) │
|
|
|
-│ │
|
|
|
-│ const chatInputActions = useChatInput({...}) │
|
|
|
-│ ↓ │
|
|
|
-│ [Single Instance] │
|
|
|
-│ ↓ │
|
|
|
-│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
|
-│ │ InputBar │ │Recommend... │ │ChatGreeting │ │
|
|
|
-│ │ │ │ │ │ │ │
|
|
|
-│ │ props: {...}│ │ props: {...}│ │ props: {...}│ │
|
|
|
-│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
|
-└─────────────────────────────────────────────────────────────┘
|
|
|
- ↓
|
|
|
- ┌─────────────────────────────────────────────────────────┐
|
|
|
- │ useTextChat (Global Store) │
|
|
|
- │ ✅ Clean! │
|
|
|
- └─────────────────────────────────────────────────────────┘
|
|
|
-```
|
|
|
-
|
|
|
-## 📊 修复效果
|
|
|
-
|
|
|
-### 性能提升
|
|
|
-- **内存使用**: 减少了2个额外的 Hook 实例
|
|
|
-- **副作用**: 从3个 `useEffect` 清理函数减少到1个
|
|
|
-- **定时器**: 避免了多个定时器的冲突
|
|
|
-
|
|
|
-### 代码质量
|
|
|
-- **可维护性**: 统一的状态管理,更容易调试和维护
|
|
|
-- **可预测性**: 消除了多实例导致的竞态条件
|
|
|
-- **架构清晰**: 清晰的数据流向,符合 React 最佳实践
|
|
|
-
|
|
|
-### 类型安全
|
|
|
-- **接口定义**: 明确的 `chatInputActions` 接口定义
|
|
|
-- **Props 传递**: 类型安全的 props 传递机制
|
|
|
-
|
|
|
-## 🎯 最佳实践总结
|
|
|
-
|
|
|
-1. **单一职责**: 每个 Hook 实例应该只负责一个特定的业务逻辑
|
|
|
-2. **状态提升**: 当多个组件需要共享状态时,将状态提升到最近的共同父组件
|
|
|
-3. **Props 传递**: 通过 props 显式传递依赖,而不是在每个组件中创建独立实例
|
|
|
-4. **副作用管理**: 确保副作用(useEffect)只在需要的地方执行一次
|
|
|
-
|
|
|
-这次修复不仅解决了多实例问题,还提高了代码的整体架构质量,使其更符合 React 的设计理念。
|