React AntDesign Form起止时间表单项变更时如何互相触发重新校验
问题背景
在React函数组件中使用AntDesign Form收集用户标注的视频事件起止时间,要求格式为HH:MM:SS,包含start-time和end-time两个表单项,自定义校验规则保证结束时间晚于开始时间。
现有表单代码如下:
const timeInput = () => { return ( <> <Form.Item name={"start-time"} hasFeedback rules={[ { required: true, message: 'Required', }, ({ getFieldValue }) => ({ validator(_, value) { return startTimeInputValidator(getFieldValue, "end-time", value) } }) ]} > <Input id="start-time-input" placeholder={"Start Time (HH:MM:SS)"} /> </Form.Item> <Form.Item name={"end-time"} hasFeedback rules={[ { required: true, message: 'Required', }, ({ getFieldValue }) => ({ validator(_, value) { return endTimeInputValidator(getFieldValue, "start-time", value) } }) ]} > <Input id="end-time-input" placeholder={"End Time (HH:MM:SS)"} /> </Form.Item> </> ) }
自定义校验器代码如下:
const regexTime = /^(?:[01]\d|2[0123]):(?:[012345]\d):(?:[012345]\d)$/; const timeInvalidDesc = "Not a Valid Time!"; const doStartTimeDesc = "Start Time Invalid!"; const timeMismatchDesc = "End Time must be after Start Time!"; export async function startTimeInputValidator(getFieldValue, field, text) { var endTime = getFieldValue(field); if (!text) { return Promise.resolve(); } if(text.length<8) { return Promise.reject(); } if (!regexTime.test(text)) { return Promise.reject(new Error(timeInvalidDesc)); } if(regexTime.test(endTime)) { let stn = timeToInt(text); let etn = timeToInt(endTime); if(stn > etn) { return Promise.reject(new Error(timeMismatchDesc)); } } return Promise.resolve(); } export async function endTimeInputValidator(getFieldValue, field, text) { var startTime = getFieldValue(field); if (!text) { return Promise.resolve(); } if(text.length<8) { return Promise.reject(); } if (!regexTime.test(text)) { return Promise.reject(new Error(timeInvalidDesc)); } if (!regexTime.test(startTime)) { return Promise.reject(new Error(doStartTimeDesc)); } let stn = timeToInt(startTime); let etn = timeToInt(text); if(stn > etn) { return Promise.reject(new Error(timeMismatchDesc)); } return Promise.resolve(); }
问题复现步骤
- 输入合法的
start-time,end-time留空:示例00:00:05 - 空 - 输入合法的
end-time,表单校验通过:示例00:00:05 - 00:00:10 - 修改
start-time为晚于end-time的值,表单校验不通过:示例00:00:15 - 00:00:10 - 修改
end-time为晚于新start-time的值,逻辑上校验应通过,但start-time字段残留错误提示:示例00:00:15 - 00:00:20
问题根源是修改其中一个时间字段时,仅会触发当前字段的校验,不会触发关联字段的重校验,导致错误残留。
解决方案
方案1:使用Form.Item的dependencies属性(推荐)
Ant Design Form.Item原生支持dependencies配置,声明当前表单项依赖的其他字段名,依赖字段值变化时会自动触发当前表单项的重校验,无需额外编写事件逻辑。
修改后代码如下:
const timeInput = () => { return ( <> <Form.Item name={"start-time"} hasFeedback dependencies={['end-time']} // 新增:依赖end-time,end-time变化时自动校验当前字段 rules={[ { required: true, message: 'Required', }, ({ getFieldValue }) => ({ validator(_, value) { return startTimeInputValidator(getFieldValue, "end-time", value) } }) ]} > <Input id="start-time-input" placeholder={"Start Time (HH:MM:SS)"} /> </Form.Item> <Form.Item name={"end-time"} hasFeedback dependencies={['start-time']} // 新增:依赖start-time,start-time变化时自动校验当前字段 rules={[ { required: true, message: 'Required', }, ({ getFieldValue }) => ({ validator(_, value) { return endTimeInputValidator(getFieldValue, "start-time", value) } }) ]} > <Input id="end-time-input" placeholder={"End Time (HH:MM:SS)"} /> </Form.Item> </> ) }
该方案符合AntD设计规范,实现成本最低。
方案2:手动调用校验方法
如果需要更灵活的控制逻辑,也可以通过form实例手动触发关联字段的校验:
const timeInput = () => { const [form] = Form.useForm(); // 获取form实例,外层传入可直接用props.form // 触发指定字段校验 const validateRelated = (field) => form.validateFields([field]); return ( <> <Form.Item name={"start-time"} hasFeedback rules={[ { required: true, message: 'Required', }, ({ getFieldValue }) => ({ validator(_, value) { return startTimeInputValidator(getFieldValue, "end-time", value) } }) ]} > <Input id="start-time-input" placeholder={"Start Time (HH:MM:SS)"} onChange={() => validateRelated('end-time')} // 新增:start-time变化时校验end-time /> </Form.Item> <Form.Item name={"end-time"} hasFeedback rules={[ { required: true, message: 'Required', }, ({ getFieldValue }) => ({ validator(_, value) { return endTimeInputValidator(getFieldValue, "start-time", value) } }) ]} > <Input id="end-time-input" placeholder={"End Time (HH:MM:SS)"} onChange={() => validateRelated('start-time')} // 新增:end-time变化时校验start-time /> </Form.Item> </> ) }
内容的提问来源于stack exchange,提问作者peytonurquhart
相关产品推荐
相关产品推荐

