Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove all async validation #2140

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Remove all async validation #2140

wants to merge 2 commits into from

Conversation

jaredpalmer
Copy link
Owner

@jaredpalmer jaredpalmer commented Dec 19, 2019

This removes async validation from Formik. (See #1524)

As for actually rolling this out, and once we figure out details, my plan would be to add check for promise in validation and put up a deprecation notices for a few releases. Since sync/async have different typescript types, I think we can make a new top-level entry called formik/sync. We will need to add docs and update examples.


Why?

When we first wrote Formik, the only reason we had async validation at all was because Yup was async. Yup has added an sync API since then. In addition, I can count on a single hand the number of times I have used async validation at the top level. In fact, when I tried a few months back to make a username checker input, I ended up not using formik validate prop on that form because you can't debounce it properly (you want to debounce on changes/blur but then not during submit). Thus it's only purpose is really to support Yup at this point. I will add more docs about best practices later, but I've found it way easier to do this sort async remote validation in a custom field or in a custom effect. The only perhaps nuance to removing this is that it's theoretically possible that you may want to validate asynchronously "prior to submit." With this change, you would move that call to be at the top of your own onSubmit function. I'm not sure this actually matters in practice though as long as your API validates (which it should anyways).

FWIW you'll be able to mimic most of the old behavior for top level async validate by just wrapping useFormik.

const useLegacyAsyncFormik = ({ validateAsync,  onSubmit, ...props }) => {
  const { values, touched, setErrors, ...formik } = useFormik({
      ...props,
      onSubmit: async (values, actions) => {
        try {
        const errors = await validateAsync(values)
        actions.setErrors(errors)
        if (Object.keys(errors).length === 0) {
          await onSubmit(values, actions)
        }
        } catch(e) {
          // handle this however you want
          return;
        }
      }
  })
  // Pretty close to identical behavior (for validateOnChange/Blur)
  React.useEffect(() => {
     let isCurrent = true;
     validateAsync(values).then(errors => {
       if (isCurrent) {
         setErrors(errors)
       }
     })
     return ()=> { isCurrent = false }
  }, [values, touched, setErrors])

  return { values, touched, setErrors, ...formik }
}

Alternatives

  • Add smarter debounce props
  • Rewrite validation to attempt to be sync, but de-opt to async if that's not possible (this could be gross).

@vercel
Copy link

vercel bot commented Dec 19, 2019

This pull request is being automatically deployed with ZEIT Now (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://zeit.co/jared/formik-docs/ordf8gvvv
🌍 Preview: https://formik-docs-git-experimental-sync.jared.now.sh

@codesandbox-ci
Copy link

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 227c8f5:

Sandbox Source
Formik TypeScript Playground Configuration

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant