Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set dynamic error messages in Yup async validation?

I am trying async validation in Formik using Yup's .test() method and need to set the error message that I get from the API. Error messages are going to be different based on some conditions in backend.

Tried few solutions mentioned here
https://github.com/jquense/yup/issues/222 and Dynamic Validation Messages Using Yup and Typescript

But Yup is throwing the default error message given in test().

Documentation says that

All tests must provide a name, an error message and a validation function that must return true or false or a ValidationError. To make a test async return a promise that resolves true or false or a ValidationError.

I am resolving a new ValidationError with the error message but still, it throws the default error.

Here is the code.

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);
          });
      });
    }
  )
});
like image 996
Murli Prajapati Avatar asked Dec 23 '22 17:12

Murli Prajapati


2 Answers

I got it working using the function syntax instead of arrow function for validation function.

Doc says:

test functions are called with a special context, or this value, that exposes some useful metadata and functions. Note that to use this context, the test function must be a function expression (function test(value) {}), not an arrow function, since arrow functions have lexical context.

Here is the working code.

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);
        });
    })
});
like image 191
Murli Prajapati Avatar answered Jan 13 '23 15:01

Murli Prajapati


Actually you're almost correct.You just need to use the following:

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

Let me know if it still doesn't work ya

like image 34
Lawrence Supian Avatar answered Jan 13 '23 16:01

Lawrence Supian