如何在Yup异步验证中设置动态错误消息?

时间:2020-07-17 08:35:57

标签: reactjs formik yup

我正在尝试使用Yup的.test()方法在Formik中进行异步验证,并且需要设置从API获得的错误消息。错误消息会根据后端的某些情况而有所不同。

尝试了此处提到的几种解决方案
https://github.com/jquense/yup/issues/222Dynamic Validation Messages Using Yup and Typescript

但是,Yup会抛出test()中给出的默认错误消息。

文档说

所有测试必须提供名称,错误消息和必须返回true或false或ValidationError的验证函数。要使测试异步进行,请返回可解决true或false或ValidationError的Promise。

我正在使用错误消息解决新的ValidationError,但仍然会引发默认错误。

这是代码。

const schema = Yup.object().shape({
  email: Yup.string().test(
    "email_async_validation",
    "Email Validation Error", // YUP always throws this error
    value => {
      return new Promise((resolve, reject) => {
        emailValidationApi(value)
          .then(res => {
            const { message } = res.data; // I want this error message to be shown in form.
            resolve(new Yup.ValidationError(message));
          })
          .catch(e => {
            console.log(e);
          });
      });
    }
  )
});

4 个答案:

答案 0 :(得分:1)

实际上,您几乎是正确的。您只需要使用以下内容:

resolve(this.createError({ message: message }));

让我知道它是否仍然无法正常工作

答案 1 :(得分:0)

不要传递第二个参数,因为我们通常将其作为错误消息传递,而是使用“ createError”创建您自己的自定义消息并根据您的条件返回它。

import * as yup from "yup";

const InitiateRefundSchema = yup.object().shape({
  amountPaid: yup.number(),
  refundAmount: yup
    .number()
    .test("test-compare a few values", function (value) {
      let value1 = this.resolve(yup.ref("amountPaid"));
      let value2 = this.resolve(yup.ref("refundAmount"));
      if (value1 < value2) {
        return this.createError({
          message: `refund amount cannot be greater than paid amount '${value1}'`,
          path: "refundAmount", // Fieldname
        });
      } else return true;
    }),
})

答案 2 :(得分:0)

我使用function语法而不是使用箭头函数作为验证功能。

医生说:

使用特殊上下文或this值调用

test函数, 展示一些有用的元数据和功能。请注意,要使用this 在上下文中,测试函数必须是函数表达式(function test(value) {}),而不是箭头函数,因为箭头函数具有 词汇语境。

这是工作代码。

const schema = Yup.object().shape({
  email: Yup.string()
    .email("Not a valid email")
    .required("Required")
    .test("email_async_validation", "Email Validation Error", function (value) { // Use function
      return emailValidationApi(value)
        .then((res) => {
          const message = res;
          console.log("API Response:", message);
          return this.createError({ message: message });
          // return Promise.resolve(this.createError({ message: message })); // This also works
        })
        .catch((e) => {
          console.log(e);
        });
    })
});

答案 3 :(得分:0)

我也可以使用箭头函数来做到这一点。

const schema = Yup.object().shape({
 email: Yup.string()
  .email("Not a valid email")
  .required("Required")
  .test("email_async_validation", "Email Validation Error", (value, {createError}) { 
    return emailValidationApi(value)
      .then((res) => {
        const message = res;
        console.log("API Response:", message);
        return createError({ message: message });
      })
      .catch((e) => {
        console.log(e);
      });
    })
  });