(是的)如何使用单个 .test() 函数创建多个错误

Ahm*_*asr 9 javascript reactjs yup formik

编辑:虽然已接受的解决方案有效,但我的用例中效果更好

我有一个函数可以验证输入字段 A输入字段 B都不为空,并且根据我的表单的构建方式,我只需编写一个函数来检查这两个字段。(实际函数要复杂得多,所以我选择创建下面的示例函数)

这是我的测试功能:

function isValid(message) {
    //I don't use the message variable but I added it anyway
    return this.test("isValid", message, function (value) {
    if(!value.A) {
        return createError({path: `${this.path}.A`, message:"A is empty"});
    }
    if(!value.B) {
        return createError({path: `${this.path}.B`, message:"B is empty"});
    }
    return true;
    })
Run Code Online (Sandbox Code Playgroud)

这样做的结果是,当 A 和 B 为空时,我返回第一个 createError,因此函数的其余部分将被跳过,这就是formik.errors对象的样子:

{
    parent: {
        A: "A is empty"
    }
}
Run Code Online (Sandbox Code Playgroud)

如何创建错误数组并返回它?

我试过:

返回 createErrors() 数组,但我得到了相同的结果,

将 createErrors 与路径和消息数组一起使用,但 formik.errors 看起来像这样:

{
    parent.A: { parent.B: "2 errors occured" }
}
Run Code Online (Sandbox Code Playgroud)

而不是所需的

{
    parent: {
        a: "A is empty",
        b: "B is empty"
    }
}
Run Code Online (Sandbox Code Playgroud)

sen*_*nya 16

您可以使用ValidationErrorfromYup来实现此目标。的构造函数ValidationError 接受其他实例的数组ValidationError。各个ValidationError实例能够保存path错误消息,父实例将组合它们

这是示例测试函数:

import { ValidationError } from 'yup'

const testFunc = (value) => {
    const keys = ['A', 'B']

    const errors = keys.map((key) => {
        if (value[key]) { return null } // Successful validation, no error

        return new ValidationError(
          `${key} is empty`,
          value[key],
          key
        )
    }).filter(Boolean)

    if (errors.length === 0) { return true }

    return new ValidationError(errors)
}
Run Code Online (Sandbox Code Playgroud)

通过源代码createError判断也可以做同样的事情。

您可以将函数而不是字符串传递给调用message的属性createErrorcreateError在这种情况下,该函数将在=> ValidationError.formatError here内调用。如果这个函数返回一个正确构建的VaildationError实例的数组,我们将得到相同的结果。

这是该方法的示例测试函数:

import { ValidationError } from 'yup'

const testFunc = (value, { createError }) => {
    const keys = ['A', 'B']

    const errors = keys.map((key) => {
        if (value[key]) { return null } // Successful validation, no error

        return new ValidationError(
          `${key} is empty`,
          value[key],
          key
        )
    }).filter(Boolean)

    if (errors.length === 0) { return true }

    return createError({
      message: () => errors
    })
}
Run Code Online (Sandbox Code Playgroud)