Published on

How to Use Conditional Validation in Formik with Yup

Authors
  • Name
    Ripal & Zalak
    Twitter

Master Conditional Validation in Yup

Conditional validation is a powerful feature of Yup, a JavaScript schema builder, allowing you to apply dynamic rules based on the values of other fields. In this article, we will explore how to effectively use this feature, particularly when integrated with Formik for managing forms in React.

Why Use Conditional Validation?

Conditional validation is essential when:

  • A field's requirement depends on another field (e.g., email is required only if a checkbox is selected).
  • You need to validate dynamic or complex forms with dependencies.

Example: Email Validation Based on Checkbox

Here's how you can use Yup's when method to conditionally validate an email field based on a checkbox:

import * as Yup from 'yup'

const validationSchema = Yup.object().shape({
  showEmail: Yup.boolean(),
  email: Yup.string()
    .email('Invalid email format')
    .when('showEmail', {
      is: true, // Condition to apply validation
      then: Yup.string().required('Email is required'),
      otherwise: Yup.string(),
    }),
})

Explanation:

  1. showEmail Field: Defined as a boolean to control the condition.
  2. when Method: Dynamically changes the validation rules based on the value of showEmail.
  3. then and otherwise: Define the behavior for true and false values.

Integration with Formik

Here’s how to use the above schema with Formik:

import { Formik, Form, Field } from 'formik'

const MyForm = () => {
  return (
    <Formik
      initialValues={{ showEmail: false, email: '' }}
      validationSchema={validationSchema}
      onSubmit={(values) => console.log(values)}
    >
      {({ errors, touched }) => (
        <Form>
          <label>
            <Field type="checkbox" name="showEmail" /> Show Email
          </label>

          {touched.showEmail && (
            <div>
              <Field name="email" placeholder="Email" />
              {errors.email && <div>{errors.email}</div>}
            </div>
          )}

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

export default MyForm

Common Pitfalls

  1. Undefined Initial Values: Always define initial values for all fields in initialValues. Without it, Yup won’t recognize the fields, leading to errors.
  2. Nested Conditions: For nested validations, use a combination of Yup.lazy or functions in when.
  3. TypeScript Issues: Ensure proper typing by using .concat for merging schemas.

Advanced Use Cases

Validating Multiple Fields

You can validate multiple dependent fields using the when method:

const schema = Yup.object().shape({
  password: Yup.string().required('Password is required'),
  confirmPassword: Yup.string().when('password', {
    is: (password) => password && password.length > 0,
    then: Yup.string().oneOf([Yup.ref('password')], 'Passwords must match'),
  }),
})

Using a Function in when

For more complex conditions:

const schema = Yup.object().shape({
  contactMethod: Yup.string().required('Contact method is required'),
  phone: Yup.string().when('contactMethod', (method, schema) => {
    return method === 'phone' ? schema.required('Phone number is required') : schema
  }),
})

FAQs

1. What is the when method in Yup?

The when method allows you to define conditional validation logic based on other fields or values in the schema.

2. Can I use when with nested objects?

Yes, use dot notation (e.g., parent.child) or Yup.lazy for deeply nested objects.

3. How do I handle multiple conditions?

You can combine multiple conditions using functions inside when or use logical operators.

4. Why am I getting a "Cannot read property of undefined" error?

Ensure all fields have initial values in initialValues when using Formik.

5. Can I validate an array conditionally?

Yes, use Yup.array().of() with conditions applied to the inner schema.

Conclusion

Conditional validation in Yup is a flexible and powerful tool for managing dynamic forms. By understanding the when method and its applications, you can create forms that are both user-friendly and robust.

For further exploration, check out the official Yup documentation.