1
votes

In my case, I have a yup schema form validation. For example:

const form = yup.object().shape({
firstName: yup.string().nullable().required(),
lastName: yup.string().nullable().required(),
country: yup.string().nullable().required()
    .test('validator', 'country is incorrect', value => {
        return new Promise((resolve, reject) => {
            api.post('url', value)
            .then(() => 
                  resolve(false))
            .catch(() => 
                  resolve(true)
        })
    }
});

Also, I want to validate country field asynchronously.


The flow should be the following:

  • Synchronous validation should run
  • IF no SYNCHRONOUS validation error
  • THEN run ASYNCHRONOUS validation
  • IF no ASYNCHRONOUS validation form should be valid

Issues that I faced:

I tried using .test() from yup but the order of validators was wrong.

For example, in this case, I want to execute the required validator and only if it's passed successfully without errors then run .test() (async validation).

How to achieve such behavior with Formik and Yup?

1
You can try the .when() yup method and make you async call when the country field is not emptyMiDas
Hello @MiDas, How to get country field in .when() method in this case? example: country: yup.string().when(what should be here, {........D.Mark
sorry. Noo need for when. You have the value of the field in your test method, check whether or not it is empty before you make the api call. If it is empty just return trueMiDas

1 Answers

0
votes

Here is how this can be achieved:

const form = yup.object().shape({
  firstName: yup.string().nullable().required(),
  lastName: yup.string().nullable().required(),
  country: yup.string().nullable().required()
    .test('validator', 'country is incorrect', value => {
      if (!_.isEmpty(value)) {
        const isDuplicateExists = await checkDuplicate(value);
        console.log("isDuplicateExists = ", isDuplicateExists);
        return !isDuplicateExists;
      }
      // WHEN THE VALUE IS EMPTY RETURN `true` by default
      return true;
    })
});

function checkDuplicate(valueToCheck) {
  return new Promise(async (resolve, reject) => {
    let isDuplicateExists;

    // EXECUTE THE API CALL TO CHECK FOR DUPLICATE VALUE
    api.post('url', valueToCheck)
    .then((valueFromAPIResponse) => {
      isDuplicateExists = valueFromAPIResponse; // boolean: true or false
      resolve(isDuplicateExists);
    })
    .catch(() => {
      isDuplicateExists = false;
      resolve(isDuplicateExists);
    })
  });
}