Antd TimePicker RangePicker设置初始值后无法修改/检测值的问题
Antd TimePicker.RangePicker 表单修改异常问题修复
问题场景
我基于Antd实现了一个带时间范围选择的编辑表单,代码如下:
组件导入
import { TimePicker } from 'antd'; const { RangePicker } = TimePicker;
状态与表单初始化
const [editForm] = Form.useForm(); const formValues = Form.useWatch([], editForm); const [editBoxVisible, setEditBoxVisible] = useState(false); const [editingMealTimeName, setEditingMealTimeName] = useState(null); const [editingMealTime, setEditingMealTime] = useState(null);
编辑触发与初始值填充
<Button type="link" size="medium" icon={<EditOutlined />} onClick={() => handleEdit(record.name, record.time)} /> const handleEdit = (name, timePeriod) => { setEditingMealTimeName(name); setEditingMealTime(timePeriod); setEditBoxVisible(true); editForm.setFieldsValue({ name: name || "", timePeriod: timePeriod ? [moment(timePeriod[0], "HH:mm"), moment(timePeriod[1], "HH:mm")] : [] }); };
模态框与表单结构
<Modal title="编辑自定义用餐时间" open={editBoxVisible} onCancel={handleEditCancel} maskClosable={false} footer={null} > <Form form={editForm} onFinish={handleEditSubmit} > <Form.Item label="名称" name="name" rules={[{ required: true }]} > <Input style={{width:"70%"}} /> </Form.Item> <Form.Item label="时间段" name="timePeriod" rules={[{ required: true }]} > <RangePicker format="HH:mm" style={{ width: "70%" }} /> </Form.Item> <Form.Item> <Button type="primary" htmlType="submit">保存</Button> </Form.Item> </Form> </Modal>
异常现象
初始值能正常显示,但修改时间时出现问题:
- 首次修改“开始时间”,确认后无法保存修改,或出现无规律的随机值
- 修改“结束时间”时,会错误记录之前的“开始时间”或更早的随机时间
- 只有清空RangePicker后重新选择,才能正常显示和保存
修复方案
1. 调整表单赋值时机,确保Modal渲染完成后再赋值
setEditBoxVisible(true)后Modal不会立刻渲染,此时直接调用setFieldsValue会因为字段未初始化导致状态异常。改用useEffect监听Modal显示状态,打开后再赋值:
import { useEffect } from 'react'; // 移除handleEdit中的setFieldsValue,只更新状态 const handleEdit = (name, timePeriod) => { setEditingMealTimeName(name); setEditingMealTime(timePeriod); setEditBoxVisible(true); }; // 监听Modal显示状态,完成渲染后赋值表单 useEffect(() => { if (editBoxVisible && editingMealTime) { editForm.setFieldsValue({ name: editingMealTimeName || "", timePeriod: [moment(editingMealTime[0], "HH:mm"), moment(editingMealTime[1], "HH:mm")] }); } }, [editBoxVisible, editingMealTime, editingMealTimeName, editForm]);
2. 为RangePicker指定valueFormat,避免moment对象引用问题
默认情况下RangePicker会返回moment对象,容易因为引用问题导致状态混乱。添加valueFormat="HH:mm"让表单直接存储字符串:
<RangePicker format="HH:mm" valueFormat="HH:mm" style={{ width: "70%" }} />
这时表单赋值也可以简化,直接传入原始字符串数组:
// useEffect中的赋值改为 editForm.setFieldsValue({ name: editingMealTimeName || "", timePeriod: editingMealTime });
3. 关闭Modal时清空表单状态(可选)
避免下次打开Modal时残留旧状态,在关闭时重置表单:
const handleEditCancel = () => { setEditBoxVisible(false); editForm.resetFields(); setEditingMealTimeName(null); setEditingMealTime(null); };
核心原因
- 表单赋值时机过早,Modal未完成渲染,表单字段未初始化导致赋值失效
- 未指定
valueFormat时,RangePicker依赖moment对象引用管理状态,外部传入的moment对象可能破坏内部状态同步
内容的提问来源于stack exchange,提问作者Asymptotes
相关产品推荐
相关产品推荐

