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

在Yup Schema中如何通过ref获取字段实际值进行计算?

Yup跨字段校验解决方案

问题描述

我需要在Yup校验Schema中,基于另一个字段的引用进行计算。尝试使用ref后,发现无法获取目标字段的实际值。ref的getValue方法似乎能满足需求,但它需要一个any类型的参数,我不知道该传入什么值。以下是我的代码示例:

const raceSchema = object({
    abilityBonuses: array()
        .of(
            object({
                bonus: number()
                    .min(-10, 'Bonus cannot be lower than -10')
                    .max(10, 'Bonus cannot be higher than 10')
                    .required('Bonus is required'),
                abilityScore: object({
                    id: string().required('Ability score id is required'),
                    name: string().required('Ability score name is required')
                })
            })
        )
        .required('Ability bonuses are required'),
    abilityBonusOptions: object({
        bonus: number()
            .min(-10, 'Bonus cannot be lower than -10')
            .max(10, 'Bonus cannot be higher than 10')
            .required('Bonus is required'),
        numberOfAbilities: number().lessThan(
            6 -
                ref<{ bonus: number; abilityScore: Item }[]>('abilityBonuses').getValue(
                    // What do I put here? Should I even be using getValue?
                ).length +
                1,
            'Sum of number of ability bonuses and ability bonus option number must be less than 6'
        )
    })
});

解决方法

别用ref.getValue(),这个方法是Yup内部调用的,手动传参根本拿不到正确值。正确做法是用Yup提供的上下文机制,通过校验方法的函数参数或自定义test逻辑来获取其他字段的值。

方案1:用lessThan的函数形式

Yup的校验方法(比如lessThan)支持传入函数,函数会接收当前字段值和上下文对象,通过context.parent就能拿到整个表单的数据:

const raceSchema = object({
    abilityBonuses: array()
        .of(
            object({
                bonus: number()
                    .min(-10, 'Bonus cannot be lower than -10')
                    .max(10, 'Bonus cannot be higher than 10')
                    .required('Bonus is required'),
                abilityScore: object({
                    id: string().required('Ability score id is required'),
                    name: string().required('Ability score name is required')
                })
            })
        )
        .required('Ability bonuses are required'),
    abilityBonusOptions: object({
        bonus: number()
            .min(-10, 'Bonus cannot be lower than -10')
            .max(10, 'Bonus cannot be higher than 10')
            .required('Bonus is required'),
        numberOfAbilities: number()
            .lessThan(
                (_, context) => {
                    // 处理可能为空的情况,避免报错
                    const bonusesLength = context.parent.abilityBonuses?.length || 0;
                    return 6 - bonusesLength + 1;
                },
                'Sum of number of ability bonuses and ability bonus option number must be less than 6'
            )
            .required('Number of abilities is required')
    })
});

方案2:自定义test校验逻辑

如果需要更复杂的判断,用test方法更灵活,通过this.parent访问其他字段:

const raceSchema = object({
    abilityBonuses: array()
        .of(
            object({
                bonus: number()
                    .min(-10, 'Bonus cannot be lower than -10')
                    .max(10, 'Bonus cannot be higher than 10')
                    .required('Bonus is required'),
                abilityScore: object({
                    id: string().required('Ability score id is required'),
                    name: string().required('Ability score name is required')
                })
            })
        )
        .required('Ability bonuses are required'),
    abilityBonusOptions: object({
        bonus: number()
            .min(-10, 'Bonus cannot be lower than -10')
            .max(10, 'Bonus cannot be higher than 10')
            .required('Bonus is required'),
        numberOfAbilities: number()
            .required('Number of abilities is required')
            .test(
                'sum-limit',
                'Sum of number of ability bonuses and ability bonus option number must be less than 6',
                function(value) {
                    const bonusesLength = this.parent.abilityBonuses?.length || 0;
                    return value < (6 - bonusesLength + 1);
                }
            )
    })
});

关键提示

  • 永远不要手动调用ref.getValue(),它是Yup内部解析引用的方法,需要传入内部上下文,外部调用无效。
  • 不管用哪种方案,都要处理字段可能为空的情况,加?.length || 0防止出现Cannot read properties of undefined的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 03:45:30