question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Debouncing Asynchronous tests via Yup

See original GitHub issue

Is your feature request related to a problem? Please describe. Just picked up vee-validate v4 for a Vue 3 application for work. I ran into my problem while trying to implement an email field with asynchronous validation towards our backend. I’m using the composition API functions useForm and useField to create custom field components and Yup to pass schemas for each field down to each field component. The schema for my email field looks like this:

email: string()
    .test({
      name: "uniqueEmailParent",
      message: $t("EMAIL_IS_NOT_UNIQUE_ERROR"),
      test: checkEmail,
      exclusive: true
    })
    .label($t("EMAIL")),

And the test function for the field looks like this.

const checkEmail = async (value, testContext) => {
      console.log("Checking email", value);
      const schema = string()
        .required()
        .email();
      try {
        schema.validateSync(value);
      } catch (err) {
        /* Returns validation error message */
        return err;
      }

      const response = await Registration.validateEmail(value);
      console.log(response);
      if (!response.valid) {
        return testContext.createError({
          message: $t("FIELD_IS_NOT_AN_EMAIL")
        });
      }
      if (!response.available) {
        return testContext.createError({
          message: $t("EMAIL_IS_NOT_UNIQUE_ERROR")
        });
      }
    return true;
  };

First I tried to find a way to run the test function after required and email rules passed, but that didn’t work so I included the two rules inside the test function and stop the function upon failing those validations there. The scenario now is: if the value passes the required and email rules it sends request every time the value for the field updates.

Describe the solution you’d like

Is there any way to debounce the checkEmail function? Prevent the test rule to run until I stopped typing for 1000 milliseconds?

Describe alternatives you’ve considered

I tried using lodash’s debounce function like this:

email: string()
    .test({
      name: "uniqueEmailParent",
      message: $t("EMAIL_IS_NOT_UNIQUE_ERROR"),
      test: debounce(checkEmail, 1000),
      exclusive: true
    })
    .label($t("EMAIL")),

But considering the returned value is function the field doesn’t pass the validation, I’m guessing since it’s not any of the accepted return values true, false or ValidationError.

If anything is poorly explained, let me know and I’ll do my best to explain further. Thank you for your efforts in this library.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
thajjdcommented, May 10, 2021

Thank you for your thorough explanation. I implemented a working solution using your example.

0reactions
logaretmcommented, May 9, 2021

I don’t think this works as well as you think:

    const debounceValidation = debounce(async (value) => {
      const response = await isEmailAvailable(value);
      return response;
    }, 500);

The way such debounce functions work is by returning a higher-order function (non-async) that returns mostly undefined, which is why I didn’t opt into time-based debouncing in the original example, the difference is that I explicitly return a promise that resolves after a set time.

This means await debounceValidation() doesn’t wait for the validation to be done which explains why the pending flag not changing, you can verify this by using then instead of await and you will notice it crashes.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to debounce async formik/yup validation, that it will ...
It looks that denounced function returns a value from the previous call. This is how lodash debounce is supposed to work:.
Read more >
Debounced callback validator #1246 - jquense/yup - GitHub
I need to do async validation with a callback, because I need the back-end API to do the validation for me - in...
Read more >
Debouncing and Throttling Explained Through Examples
Debounce and throttle are two similar (but different!) techniques to control how many times we allow a function to be executed over time....
Read more >
Testing Caveats | VeeValidate
Asynchronous Testing. TIP. The following examples will use vue-test-utils API to conduct the tests. After triggering an event like an input event, ...
Read more >
Debouncing async Tasks - Alexander Wichmann Carlsen
The test simply creates a Function that adds 1 to i every time it is run. When putting it through the Collapser ,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found