React父组件状态更新后子AddEditProductModal未重渲染问题排查
问题根本原因
你观测到父组件productInfo状态已更新是正确的,子组件也确实触发了重渲染,问题出在两点:
- AntD Form 的
initialValues特性限制:initialValues仅在 Form 组件首次挂载时初始化表单值,后续该 prop 发生变化时,Form 不会主动同步更新已有的表单值,这是 AntD 表单的默认设计。 - 弹窗未销毁内部组件:AntD Modal 默认关闭时只会隐藏弹窗,不会销毁内部的 Form 组件,所以第一次打开弹窗时 Form 挂载初始化了第一个产品的值,后续打开弹窗 Form 始终是之前的实例,不会重新读取新的
productInfo初始化。 - 额外小隐患:你父组件更新
productInfo用了旧状态合并新状态的写法{...prevProductInfo, ...currentProductInfo},如果前一个产品存在当前产品没有的字段,会残留旧数据。
解决办法(任选其一即可)
方案1:给 Modal 加 destroyOnClose 属性
直接修改子组件的 Modal 标签,添加 destroyOnClose={true},这样每次关闭弹窗时会销毁内部所有子元素,下次打开弹窗 Form 会重新挂载,自动读取最新的 initialValues:
<Modal title={title} visible={visible} onOk={onOk} onCancel={onCancel} destroyOnClose={true} // 新增这行 >
方案2:给 Form 加唯一 key
给 Form 组件绑定和产品唯一标识关联的 key,每次选择不同产品时 key 变化,Form 会自动销毁重建:
<Form name="basic" key={productInfo.key} // 新增这行,用产品的唯一key作为Form的key labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} onFinish={onFinish} initialValues={productInfo} >
方案3:手动监听 productInfo 变化更新表单
子组件内部用 Form.useForm() 获取表单实例,通过 useEffect 监听 productInfo 变化,手动调用 setFieldsValue 更新表单:
const AddEditProductModal = ({ title, visible, productInfo, onOk, onCancel, onFinish }) => { const [form] = Form.useForm(); // 新增获取form实例 // 新增监听productInfo变化,更新表单值 useEffect(() => { if (productInfo) { form.setFieldsValue(productInfo); } }, [productInfo, form]); return ( <Modal title={title} visible={visible} onOk={onOk} onCancel={onCancel} > <Form form={form} // 把form实例绑定到Form组件 name="basic" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} onFinish={onFinish} initialValues={productInfo} > {/* 其余表单项保持不变 */} </Form> </Modal> )}
额外优化建议
父组件的 showEditModal 方法里,如果你每次传入的 currentProductInfo 是完整的产品对象,不需要合并旧状态,直接赋值即可避免残留旧字段:
setProductInfo(currentProductInfo);
内容的提问来源于stack exchange,提问作者Crusaderpyro
相关产品推荐
相关产品推荐

