问题场景:
这个bug涉及到两个独立的状态管理域:
const [form] = Form.useForm();
// 内部维护表单字段值
// 生命周期:从组件创建到手动重置
// 清理方式:form.resetFields()
特性:
form.resetFields()
interface FormState {
formData: Record<string, any>;
}
// 存储表单数据的副本
// 用于跨组件共享
特性:
第一次注册成功
↓
触发事件:registerWork API 返回 code === '0x000000'
↓
当前行为(Bug原因):
- ✅ Redux viewSelection.selectedViews 被清空
- ❌ Redux formSlice.formData 未清空
- ❌ Ant Design Form 内部状态未清空
↓
状态不一致:
- UI层:表单显示为空(用户视角)
- 数据层:form.getFieldsValue() 返回旧数据(系统视角)
↓
第二次注册
↓
用户操作:只选择体位,不填表单
↓
点击"注册"按钮
↓
handleRegister() 执行:
1. let values = form.getFieldsValue();
// ❌ 返回第一次的完整数据(用户不知道)
2. validateResult = schema.safeParse(values);
// ✅ 验证通过(因为values有完整数据)
3. 调用 registerWork(registerInfo);
// ❌ 使用旧数据注册成功
↓
Bug结果:用户以为表单是空的,实际用旧数据注册成功
在两个关键时机清理双重状态:
文件:src/states/patient/register/formSlice.ts
const formSlice = createSlice({
name: 'form',
initialState,
reducers: {
setFormData: (state, action) => {
state.formData = action.payload;
},
// ✅ 新增:清空表单数据
clearFormData: (state) => {
state.formData = {};
console.log('Redux formSlice: 表单数据已清空');
},
},
});
export const { setFormData, clearFormData } = formSlice.actions;
领域概念:
{}
文件:src/pages/patient/Register.tsx
const response = await registerWork(registerInfo);
if (response.code !== '0x000000') {
message.error(`注册失败: ${response.description}`);
return { success: false, views: [] };
}
// ✅ 注册成功后的三重清理
// 1. 清理 Redux formSlice
dispatch(clearFormData());
// 2. 清理 Ant Design Form
form.resetFields();
// 3. selectedViews 已在 viewSelectionSlice 中自动清空
console.log('注册成功,表单已清空,可以开始新的注册');
return { success: true, data: response.data, views: selectedViews };
因果关系:
API返回成功
↓
触发清理三重奏:
1. dispatch(clearFormData()) → Redux formSlice.formData = {}
2. form.resetFields() → Ant Design Form 内部状态清空
3. selectedViews自动清空 → 已在viewSelectionSlice实现
↓
系统恢复初始状态
↓
用户可以开始新的注册流程 ✅
文件:src/pages/patient/Register.tsx
// 清理时机3:组件卸载时清理表单
useEffect(() => {
return () => {
// 组件卸载时清理
dispatch(clearFormData());
form.resetFields();
console.log('注册页面已卸载,表单数据已清空');
};
}, [dispatch, form]);
领域概念:
用户进入注册页面
↓
填写患者信息
↓
每次字段变化 → dispatch(setFormData(allValues))
↓
选择体位
↓
点击体位 → dispatch(addSelectedView(view))
↓
点击"注册"按钮
↓
handleRegister():
1. 获取表单值:form.getFieldsValue()
2. 验证表单:schema.safeParse(values)
3. 验证通过 → 调用API:registerWork(registerInfo)
↓
API返回成功
↓
【三重清理】
1. dispatch(clearFormData())
→ formSlice.formData = {}
2. form.resetFields()
→ Form内部状态清空
3. selectedViews自动清空
→ viewSelection.selectedViews = []
↓
显示成功消息
↓
用户可以开始新的注册 ✅
用户填写部分信息
↓
未完成注册,切换到其他页面
↓
RegisterPage组件卸载
↓
useEffect cleanup函数执行
↓
【清理】
1. dispatch(clearFormData())
2. form.resetFields()
↓
用户再次进入注册页面
↓
看到的是干净的空表单 ✅
┌─────────────────────────────────────────────┐
│ 注册成功后的状态 │
├─────────────────────────────────────────────┤
│ Redux viewSelection.selectedViews: [] ✅ │
│ Redux formSlice.formData: {...旧数据} ❌ │
│ Ant Design Form State: {...旧数据} ❌ │
└─────────────────────────────────────────────┘
↓
状态不一致!
↓
第二次注册时Bug
┌─────────────────────────────────────────────┐
│ 注册成功后的状态 │
├─────────────────────────────────────────────┤
│ Redux viewSelection.selectedViews: [] ✅ │
│ Redux formSlice.formData: {} ✅ │
│ Ant Design Form State: {} ✅ │
└─────────────────────────────────────────────┘
↓
状态一致!
↓
系统恢复初始状态
onValuesChange
→ dispatch(setFormData)
用户操作 → 状态变化 → 副作用处理 → UI更新
测试场景1:连续注册两次
测试场景2:填写后离开页面
form.getFieldsValue()
返回空对象formSlice.formData
为空对象selectedViews
为空数组src/states/patient/register/formSlice.ts
clearFormData
actionsrc/pages/patient/Register.tsx
clearFormData
, useEffect
src/states/patient/viewSelection/index.ts
(selectedViews的清理)src/hooks/useRegisterState.ts
(状态获取)src/validation/patient/registerSchema.ts
(验证逻辑)日期 | 修改人 | 修改内容 |
---|---|---|
2025/10/8 | - | Bug分析、修复实现、文档创建 |