Redux状态变更时表单数据无法同步渲染问题求助
问题分析与解决方案
问题根源
defaultValues依赖缺失:useMemo仅监听currentUser,未包含customer和isEdit,导致Redux中customer更新时,defaultValues不会重新生成,始终携带旧数据。- 表单未同步Redux更新:
useEffect未监听customer的变化,API返回新数据更新Redux后,没有触发表单重置逻辑,无法将新数据同步到表单控件。 - 异步数据时序问题:初始渲染时
customer为空,表单先以旧值/空值渲染,后续customer更新后无同步机制。
具体修改步骤
1. 修正defaultValues的依赖项
将customer和isEdit加入useMemo的依赖数组,确保这两个值变化时,defaultValues能重新计算为最新数据:
const defaultValues = useMemo( () => ({ email: isEdit ? customer?.email : '', name: isEdit ? customer?.name : '', }), [isEdit, customer, currentUser] // 补充isEdit和customer依赖 )
2. 监听customer变化,同步更新表单
修改useEffect,新增customer依赖,当isEdit为true且customer存在时,调用reset将表单值更新为最新的defaultValues:
useEffect(() => { if (isEdit) { dispatch(getCustomerDetails(id)); } // 当编辑状态或客户数据变化时,重置表单 if (isEdit && customer) { reset(defaultValues); } else if (!isEdit) { reset(defaultValues); } }, [isEdit, id, customer, defaultValues, reset, dispatch]); // 移除eslint禁用注释,补全依赖
3. 可选:添加加载状态优化(提升用户体验)
在组件渲染前判断,若处于编辑模式且customer未加载完成,显示加载状态:
if (isEdit && !customer) { return <CircularProgress />; // 替换为项目中使用的加载组件 }
完整修改后的核心代码片段
const CustomerNewEditForm = ({ isEdit, id, currentUser}) => { const dispatch = useDispatch() const navigate = useNavigate() const { customer } = useSelector((state) => state.customers) const { enqueueSnackbar } = useSnackbar() // 修正defaultValues依赖 const defaultValues = useMemo( () => ({ email: isEdit ? customer?.email : '', name: isEdit ? customer?.name : '', }), [isEdit, customer, currentUser] ) const methods = useForm({ resolver: yupResolver(NewUserSchema), defaultValues }) const { reset, watch, control, setValue, handleSubmit, formState: { isSubmitting } } = methods const values = watch() // 修正useEffect逻辑与依赖 useEffect(() => { if (isEdit) { dispatch(getCustomerDetails(id)) } if (isEdit && customer) { reset(defaultValues) } else if (!isEdit) { reset(defaultValues) } }, [isEdit, id, customer, defaultValues, reset, dispatch]) // 其余onSubmit与渲染代码保持不变 }
原理说明
useMemo依赖customer后,Redux中客户数据更新时,defaultValues会自动重新生成最新的表单初始值。useEffect监听customer变化,一旦异步请求返回新数据,立即调用reset将表单值同步为最新数据,实现表单与Redux状态的联动。- 补全依赖项并移除eslint禁用注释,避免闭包捕获旧值导致的更新不及时问题。
内容的提问来源于stack exchange,提问作者Iqra Moazzama
相关产品推荐
相关产品推荐

