Yup schema - `when` method is not working

Viewed 1733

Recently I am suffering with creating yup schema. Since I am doing it I see that the method when() totally doesn't work for me like it should as documentation said and other solutions I found on the internet. When my checkbox is checked to true all the fields on the schema should be required, but they don't. As seen in my example I tried three ways, and none of them is working. Maybe there is someone who knows what am I doing wrong?

My test code is:

import "./styles.css";
import * as yup from "yup";
import { FormProvider, useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import React, { useEffect } from "react";

export default function App() {
  const schema = yup.object({
    isRequired: yup.bool(),
    firstName: yup.string().when("isRequired", (_, schema) => {
      return schema.required();
    }),
    lastName: yup.string().when("isRequired", () => {
      return yup.string().required();
    }),
    contact: yup.string().when("isRequired", {
      is: true,
      then: yup.string().required("Required")
    })
  });

  const methods = useForm({
    mode: "all",
    defaultValues: {
      isRequired: true,
      firstName: "",
      lastName: "",
      contact: ""
    },
    resolver: yupResolver(schema),
    shouldUnregister: true
  });

  const { register, watch } = methods;
  const isRequired = watch("isRequired");

  useEffect(() => {
    console.log(schema.fields);
  }, [isRequired, schema]);

  return (
    <FormProvider {...methods}>
      <form autoComplete="off" noValidate>
        <input type="checkbox" {...register("isRequired")} />
        <input {...register("firstName")} />
        <input {...register("lastName")} />
        <input {...register("contact")} />
      </form>
    </FormProvider>
  );
}

https://codesandbox.io/s/infallible-wildflower-dsyon

1 Answers

You third solution of how to use when was correct. The reason why it wasn't working is that in your first two when statements for firstName and lastName you always return yups required method without checking if isRequired is true.

const schema = yup.object({
  isRequired: yup.bool(),
  firstName: yup.string().when("isRequired", {
    is: true,
    then: yup.string().required()
  }),
  lastName: yup.string().when("isRequired", {
    is: true,
    then: yup.string().required()
  }),
  contact: yup.string().when("isRequired", {
    is: true,
    then: yup.string().required("Required")
  })
});

Edit xenodochial-snowflake-eo9f5

And here is how it would be done when passing a function to when.

const schema = yup.object({
  isRequired: yup.bool(),
  firstName: yup
    .string()
    .when("isRequired", (isRequired, schema) =>
      isRequired ? yup.string().required() : schema
    ),
  lastName: yup
    .string()
    .when("isRequired", (isRequired, schema) =>
      isRequired ? yup.string().required() : schema
    ),
  contact: yup
    .string()
    .when("isRequired", (isRequired, schema) =>
      isRequired ? yup.string().required() : schema
    )
});

Edit practical-pond-49vc4

Related