Value type error message displaying instead of required error message on empty input submission
Asked Answered
D

2

3

I'm using react-hook-form and yup together and for some reason it's displaying the wrong error message.

When the phone number input is left empty on submitting the form, it displays the typeError error message instead of the 'required' error message which I can't understand why that's happening since the input field is blank and there's no value to determine that it's of type 'number' or not.

import { yupResolver } from "@hookform/resolvers/yup";
import { useForm } from "react-hook-form";
import * as yup from "yup";

const schema = yup.object().shape({
  name: yup.string().required("Field is required*"),
  email: yup.string().email().required("Field is required*"),
  phoneNumber: yup
    .number()
    .required("Field is required*") //this message should be displayed instead of typeError message
    .typeError("Value must be a number*"),
  message: yup.string().required("Please provide your message*")
});


export default function App() {
  const {
    reset,
    register,
    handleSubmit,
    formState: { errors }
  } = useForm({ resolver: yupResolver(schema) });

  const submitForm = (data) => {
    console.log(data);
    reset();
  };


  return (
    <div className="App">
               <form className="contact-form" onSubmit={handleSubmit(submitForm)}>
            <h2>Send Us a Message </h2>
            <p>
              <label for="name">Name</label>
              <input name="name" type="text" {...register("name")} />
              <p className="error-msg"> {errors.name?.message} </p>
            </p>

            <p>
              <label for="email">Email</label>
              <input name="email" type="text" {...register("email")} />
              <p className="error-msg"> {errors.email?.message} </p>
            </p>

            <p>
              <label for="phoneNumber">Phone</label>
              <input
                name="phoneNumber"
                type="text"
                {...register("phoneNumber")}
              />
            </p>
            <p className="error-msg"> {errors.phoneNumber?.message} </p>
            <input type="submit"  id="submit" />
            </form>
    </div>
  );
Destrier answered 6/10, 2021 at 6:45 Comment(0)
A
1

Because Yup receives an empty string instead of a number, it thinks you're passing the wrong type. You need to tell RHF to return undefined if the input is empty:

<input
  name="phoneNumber"
  type="text"
  {...register("phoneNumber", {
    setValueAs: (v) => {
      return v === "" ? undefined : parseInt(v, 10);
    }
  })}

Codesandbox Demo

Amygdaloid answered 6/10, 2021 at 7:3 Comment(0)
T
2

A transform is the best way to address this. It has access to the original value, so you can check if it was an empty string and transform that to undefined, which triggers the required message.

phoneNumber: yup
  .number()
  .transform((val,orig) => orig == "" ? undefined : val)
  .required("Field is required*")
  .typeError("Value must be a number*")

Or if you also want a string with spaces to count as empty, something like this:

.transform((val, orig) => (typeof orig === "string" && orig.trim() === "") ? undefined : val)

This sticks to the idea that the schema defines all the conversions and checks. No need to have extra code in the register call to parse/check the value. The whole point of yup is that yup is the one parsing/checking values.

See also https://github.com/jquense/yup/issues/298 which proposes a whole bunch of different approaches and slight variations on this.

Tilney answered 24/10, 2023 at 22:49 Comment(0)
A
1

Because Yup receives an empty string instead of a number, it thinks you're passing the wrong type. You need to tell RHF to return undefined if the input is empty:

<input
  name="phoneNumber"
  type="text"
  {...register("phoneNumber", {
    setValueAs: (v) => {
      return v === "" ? undefined : parseInt(v, 10);
    }
  })}

Codesandbox Demo

Amygdaloid answered 6/10, 2021 at 7:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.