Antd Modal内使用Form出现useForm警告及重新打开后数据不更新问题
问题根因
你遇到的两个异常都是组件定义方式和状态管理逻辑错误导致的,具体问题如下:
useForm实例警告:你把包含Form的EventContent组件定义在点击事件回调sendeventdata内部,首次渲染App的时候Form组件根本没有挂载,useForm实例找不到绑定的Form元素就会抛出警告,同时你给Modal传的form属性完全无效,Antd的Modal组件本身不支持这个参数。- 弹窗重开数据不更新:你没有用React状态存储点击传入的事件数据,且Form的
initialValues仅在组件首次挂载时生效,后续打开弹窗时没有主动更新表单值,就算加了destroyOnClose,因为组件嵌套定义的逻辑问题,新的事件数据也没法正确传入表单。
修复方案
第一步:调整组件定义位置,不要嵌套声明组件
组件嵌套在其他函数/组件内部会导致每次父组件渲染时都生成新的组件实例,状态无法正常同步,把EventContent和MyModal都挪到App组件外部定义,通过props传递需要的参数。
第二步:新增状态存储弹窗和事件数据
在App组件顶层声明状态管理弹窗显隐和当前选中的事件数据,修复后的完整参考代码如下:
import { useState, useEffect } from 'react'; import { Form, Modal, Button, DatePicker, TimePicker } from 'antd'; import moment from 'moment'; // 把EventContent挪到外部定义 const EventContent = ({ form, event, l, preferredDateFormat, setValueDate, onUpdate, handleDelete }) => { // 表单打开时主动赋值,不受initialValues仅首次生效的限制 useEffect(() => { if (event) { form.setFieldsValue({ datePicker: moment(event.start), timeRangePicker: [moment(event.start), moment(event.end)], }) } }, [event, form]) return ( <div> <Form form={form} labelAlign="left" layout="vertical" > <Form.Item name="datePicker" label={l.availability.date}> <DatePicker className="w-100" format={preferredDateFormat} onChange={setValueDate} /> </Form.Item> <Form.Item name="timeRangePicker" label={l.availability.StartToEnd}> <TimePicker.RangePicker className="w-100" format="HH:mm" /> </Form.Item> <span className="d-flex justify-content-end"> <Button className="ml-1 mr-1" onClick={() => { form .validateFields() .then((values) => { onUpdate(values) form.resetFields() }) .catch((info) => { console.log('Validate Failed:', info) }) }} > {l.availability.updateBtn} </Button> <Button danger className="ml-1 mr-1" onClick={handleDelete}> Delete </Button> </span> </Form> </div> ) } // 把MyModal也挪到外部定义 const MyModal = ({ visible, title, onClose, children }) => { return ( <Modal onCancel={onClose} title={title} visible={visible} footer={null} destroyOnClose > {children} </Modal> ) } function App () { const [form] = Form.useForm(); // 新增状态管理弹窗和事件数据 const [modalVisible, setModalVisible] = useState(false); const [currentEvent, setCurrentEvent] = useState(null); const [modalTitle, setModalTitle] = useState(''); const sendeventdata = (e) => { // 点击时存储事件数据和弹窗配置,打开弹窗 setCurrentEvent(e.event); setModalTitle(e.title); setModalVisible(true); } const handleModalClose = () => { setModalVisible(false); setCurrentEvent(null); form.resetFields(); } // 剩余业务逻辑:setValueDate、onUpdate、handleDelete、多语言配置l、日期格式preferredDateFormat等自行补充 return ( <div> <MyModal visible={modalVisible} title={modalTitle} onClose={handleModalClose} > {currentEvent && <EventContent form={form} event={currentEvent} l={l} preferredDateFormat={preferredDateFormat} setValueDate={setValueDate} onUpdate={onUpdate} handleDelete={handleDelete} />} </MyModal> <Button onClick={sendeventdata}>打开弹窗</Button> </div> ) }
核心修复点说明
- 移除了Modal上无效的
form属性,仅在Form组件上绑定form实例,且保证Form组件挂载时form实例已经初始化完成,不会再抛出未关联的警告 - 弹窗打开时通过
form.setFieldsValue主动更新表单值,每次打开弹窗都会用最新的事件数据填充表单 - 关闭弹窗时主动重置表单,清空缓存的旧数据
内容的提问来源于stack exchange,提问作者WildThing
相关产品推荐
相关产品推荐

