React + Formik + Yup async validation
Asked Answered
S

2

9

Formik + yup validation with .test() triggers on change on every field

example: i have a validation schema:

const schemaValidation = yup.object().shape({
  name: yup.string().required(),
  email: yup.string().email().required()
    .test( // it runs even if previous validation failed!
      'checkEmailExists', 'email already taken.',
      // it triggers on every onBlur
      email => { console.log('email registration runs') return Promise.resolve(true)}
    ),
  other: yup.string().required()
     .test(
      'checkOthers', 'error', 
      val => {console.log('other validation runs'); return Promise.resolve(true)}
    )
})

render function on my react component looks like:

...
render () {
 return(
  <Formik
    validateOnChange={false}
    validateOnBlur={true}
    initialValues={{
      name: '',
      email: '',
      other: ''
    }}
    validationSchema={schemaValidation}
    onSubmit={this.handleSubmit}
  >
    {(props) => (
    <Form>
      <div className="field">
        <Field className="input" type="email" name="email" placeholder="Email" />
        <ErrorMessage name="email" />
      </div>

      <div className="field">
        <Field className="input" type="text" name="name" placeholder="Name"/>
        <ErrorMessage name="name" />
      </div>

      <div className="field">
        <Field className="input" type="text" name="other" placeholder="Other"/>
        <ErrorMessage name="other" />
      </div>

      <button type="submit">Submit</button>
    </Form>
    )}
  </Formik>
 )

so after every single field changed I receive messages from all .test() validators in console:

email registration runs
other validation runs

versions: react: 16.13.1 formik: 2.1.4 yup: 0.28.4

Sterile answered 23/4, 2020 at 5:40 Comment(3)
Oh wow, it's been a year, I have the similar feature like yours. But I'm out of luck. I can't seem to find any right answer. yup also didn't accept validation chain. Have you find your own solution now? @SterileBelshin
Are find any solution for this I am also stuck in the same @SterileEnsue
I'm also stuck on the same issue.Rowboat
W
0

By default formik validates after change, blur and submit events. Your code disables validation after change events with validateOnChange={false}. In order to only validate on submit events, try setting validateOnBlur to false too.

https://jaredpalmer.com/formik/docs/guides/validation#when-does-validation-run https://jaredpalmer.com/formik/docs/api/formik#validateonblur-boolean

Wiltshire answered 23/4, 2020 at 7:31 Comment(4)
validateOnBlur is behavior i want. but i wanna to validate only field i had edit, not whole formSterile
Thanks for the clarification, try the following approach directly on your Field components: jaredpalmer.com/formik/docs/api/field#validateWiltshire
i wrote validator for single Field whom return Promise, but it still work the same. no matter which field trigger onChange, single validator runs.Sterile
"The function will respect the validateOnBlur and validateOnChange config/props specified in the <Field>'s parent <Formik> / withFormik."Ploce
I
0

Hello everyone in 2022,

I understand a lot of formik has changed over the years - but thought I share a relevant solution that's using touched property, feel free to peek at https://codesandbox.io/s/stack-overflow-54204827-llvkzc.

And also shared for another StackOverflow question here, React Native Form Validation.

In summary, it's basically used like below (with yup outside of this snippet), to decide whether to show (if any) input validation errors:

      <Formik
        initialValues={{
          email: "",
          password: ""
        }}
        validationSchema={LoginSchemaA}
        onSubmit={(
          values: Values,
          { setSubmitting }: FormikHelpers<Values>
        ) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            setSubmitting(false);
          }, 500);
        }}
      >
        {({ errors, touched }) => (
          <Form>
            <label htmlFor="email">Email</label>
            <Field
              id="email"
              name="email"
              placeholder="[email protected]"
              type="email"
            />
            {errors.email && touched.email ? (
              <div style={{ color: "red" }}>{errors.email}</div>
            ) : null}

            <label htmlFor="password">Password</label>
            <Field id="password" name="password" type="password" />
            {errors.password && touched.password ? (
              <div style={{ color: "red" }}>{errors.password}</div>
            ) : null}

            <button type="submit">Submit</button>
          </Form>
        )}
      </Formik>

And as package.json reference, below are the defined versions:

"dependencies": {
    ...
    "formik": "2.2.9",
    ...
    "yup": "0.32.11"
  },

Hope this helps for those on these mentioned formik and yup versions above!

Inigo answered 11/8, 2022 at 12:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.