You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Hook Form中基于其他选择框值的Yup校验循环依赖问题

React Hook Form + Yup 解决 dropOffTime 校验循环依赖问题

问题场景

使用React Hook Form实现两个时间选择框pickUpTime和dropOffTime,选项来自按15分钟间隔排序的数组IntervalTime:

const IntervalTime = [
    '09:00',
    '09:15',
    '09:30',
    // ... 其他时间选项
]

想要实现dropOffTime不能早于pickUpTime的校验逻辑,最初尝试用Yup的when方法通过索引比较,代码如下:

resolver: yupResolver(yup.object({
    pickUpTime: yup.string().required(t('required')),
    dropOffTime: yup.string().when(['pickUpTime', 'dropOffTime'], {
        is: (pickUpTime, dropOffTime) =>
            IntervalTime.indexOf(dropOffTime) < IntervalTime.indexOf(pickUpTime),
        then: yup.string().required('Drop off time must be after pick up time'),
    }),
}))

执行后触发循环依赖错误:

Error: Cyclic dependency, node was:"dropOffTime"

问题原因

Yup的when方法依赖数组中包含了当前正在校验的字段dropOffTime,导致校验逻辑需要引用自身的值来完成判断,形成循环引用。

解决方案

改用Yup的test方法替代when,通过this.parent获取表单中pickUpTime的值,避免依赖当前字段自身:

resolver: yupResolver(yup.object({
    pickUpTime: yup.string().required(t('required')),
    dropOffTime: yup.string()
        .required(t('required'))
        .test(
            'drop-off-after-pick-up', // 校验规则名称
            'Drop off time must be after pick up time', // 错误提示
            function(value) {
                // 从表单上下文获取pickUpTime的值
                const { pickUpTime } = this.parent;
                // 空值由required规则处理,这里直接返回true跳过校验
                if (!pickUpTime || !value) return true;
                // 比较两个时间在数组中的索引,确保dropOffTime不早于pickUpTime
                return IntervalTime.indexOf(value) >= IntervalTime.indexOf(pickUpTime);
            }
        ),
}))

逻辑说明

  1. 保留required校验处理空值情况,避免重复判断
  2. 通过this.parent访问表单的其他字段值,绕开循环依赖问题
  3. 直接比较两个时间在IntervalTime数组中的索引,判断时间先后顺序

内容的提问来源于stack exchange,提问作者dnlgrs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:52:16