React Formik校验:如何实现多日期条目无重叠验证
解决Formik中多条日期条目无重叠校验问题
你可以通过两种方式实现这个校验:自定义Formik validate函数或者扩展Yup的数组校验规则,以下是具体实现:
方法一:使用Formik自定义validate函数
直接在Formik的validate属性中编写重叠校验逻辑,适合需要灵活控制错误提示位置的场景:
const validate = (values) => { const errors = {}; const { entries } = values; // 检查日期条目是否存在重叠 const hasOverlap = entries.some((entry, index) => { return entries.some((otherEntry, otherIndex) => { if (index === otherIndex) return false; // 跳过自身对比 // 转换为数字类型(确保时间戳可比较) const entryStart = Number(entry.startDate); const entryEnd = Number(entry.endDate); const otherStart = Number(otherEntry.startDate); const otherEnd = Number(otherEntry.endDate); // 核心重叠判断逻辑:覆盖部分重叠、完全包含等所有情况 return entryStart < otherEnd && entryEnd > otherStart; }); }); if (hasOverlap) { errors.entries = '日期条目存在重叠,请调整'; // 若需要给具体重叠的条目单独标错,可遍历条目并给errors.entries[index]赋值错误信息 } return errors; };
在Formik组件中使用:
<Formik initialValues={{ entries: [] }} validate={validate} onSubmit={(values) => { // 提交逻辑 }} > {/* 表单渲染内容 */} </Formik>
方法二:扩展Yup Schema的test方法
如果你已经在用Yup做格式校验,可以把重叠逻辑整合到Schema中,保持校验规则统一:
import * as Yup from 'yup'; // 单个日期条目的基础校验规则 const EntrySchema = Yup.object().shape({ entryId: Yup.number().required(), startDate: Yup.number().required('开始日期不能为空'), endDate: Yup.number() .required('结束日期不能为空') .moreThan(Yup.ref('startDate'), '结束日期必须晚于开始日期'), }); // 表单整体校验规则,添加条目重叠校验 const FormSchema = Yup.object().shape({ entries: Yup.array() .of(EntrySchema) .test( 'no-overlap', '日期条目存在重叠,请调整', function(entries) { if (!entries || entries.length <= 1) return true; // 无条目或单一条目无需校验 // 遍历所有条目对,检查是否重叠 for (let i = 0; i < entries.length; i++) { const entry = entries[i]; for (let j = i + 1; j < entries.length; j++) { const otherEntry = entries[j]; const entryStart = Number(entry.startDate); const entryEnd = Number(entry.endDate); const otherStart = Number(otherEntry.startDate); const otherEnd = Number(otherEntry.endDate); if (entryStart < otherEnd && entryEnd > otherStart) { // 返回错误,可指定错误路径到具体条目(比如`entries[${i}]`) return this.createError({ path: 'entries', message: '日期条目存在重叠,请调整', }); } } } return true; } ), });
在Formik中使用这个Schema:
<Formik initialValues={{ entries: [] }} validationSchema={FormSchema} onSubmit={(values) => { // 提交逻辑 }} > {/* 表单渲染内容 */} </Formik>
关键说明
- 日期重叠判断逻辑
entryStart < otherEnd && entryEnd > otherStart可以覆盖所有重叠场景:包括A条目部分覆盖B、A完全包含B、B完全包含A等情况。 - 如果需要给具体重叠的条目单独提示错误,可以调整错误的
path属性(比如entries[${i}]),并在表单对应位置渲染该错误。
内容的提问来源于stack exchange,提问作者Oliver Wagner
相关产品推荐
相关产品推荐

