Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'isValid' is always false

I am using custom register in react-hook-form, and I am unable to get formState.isValid to be true when I enter text into the input (and so satisfy the required condition).

Here is an example code:

interface FormValues {
  readonly value: string;
}

export default function App() {
  console.log("rendering");

  const form: UseFormMethods<FormValues> = useForm<FormValues>({
    mode: "onChange",
    reValidateMode: "onChange",
    defaultValues: { value: "" }
  });

  useEffect(() => {
    form.register({ name: "value" }, { required: true });
  }, [form, form.register]);

  const { isValid } = form.formState;
  const value = form.watch("value");

  return (
    <div>
      <input
        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
          form.setValue("value", e.target.value);
        }}
      />
      <div>IsValid: {JSON.stringify(isValid)}</div>
      <div>Errors: {JSON.stringify(form.errors)}</div>
      <div>Value: {JSON.stringify(value)}</div>
    </div>
  );
}

The question is sepcifically for this type of register use, not other types (ref or Controller).

Here is a full example.

Does someone know why this is the case, what am I missing?

Additionally, but this is less relevant - does anyone know why rendering is triggered twice for each input change?

EDIT

After discussion with Dennis Vash, there was some progress on this issue, but it is still not resolved.

The docs at https://react-hook-form.com/api/#setValue actually do specify an option for triggering validation:

(name: string, value: any, shouldValidate?: boolean) => void


You can also set the shouldValidate parameter to true in order to trigger a field validation. eg: setValue('name', 'value', true)

At the time when I am writing this, the docs refer to version 5 of react-form-hook, I am actually using 6.0.0-rc.5 so the signature changed a bit to something similar to the following:

(name: string, value: any, { shouldValidate: boolean; shouldDirty: boolean; }) => void

However, in an example that I have when using shouldValidate: true, I get an infinite loop:

interface FormValues {
  readonly value: string;
}

export default function App() {
  console.log("rendering");

  const form: UseFormMethods<FormValues> = useForm<FormValues>({
    mode: "onChange",
    reValidateMode: "onChange",
    defaultValues: { value: "" }
  });

  useEffect(() => {
    form.register({ name: "value" }, { required: true, minLength: 1 });
  }, [form, form.register]);

  const { isValid } = form.formState;
  const value = form.getValues("value");

  return (
    <div>
      <input
        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
          form.setValue("value", e.target.value, {
            shouldValidate: true
          });
        }}
      />
      <div>IsValid: {JSON.stringify(isValid)}</div>
      <div>Errors: {JSON.stringify(form.errors)}</div>
      <div>Value: {JSON.stringify(value)}</div>
    </div>
  );
}

The loop is occurring when isValid is true, but stops when it is false.

You can try it out here. Entering a key will start the continuous re-rendering, and clearing the input will stop the loop...

enter image description here

like image 319
mrzli Avatar asked Jun 23 '20 10:06

mrzli


People also ask

Why is Model IsValid false?

IsValid is false now. That's because an error exists; ModelState. IsValid is false if any of the properties submitted have any error messages attached to them. What all of this means is that by setting up the validation in this manner, we allow MVC to just work the way it was designed.

How do you make a ModelState IsValid false?

AddModelError("Region", "Region is mandatory"); ModelState. IsValid will then return false.

What does ModelState IsValid validate?

ModelState. IsValid indicates if it was possible to bind the incoming values from the request to the model correctly and whether any explicitly specified validation rules were broken during the model binding process.

What is model state IsValid?

ModelState.IsValid property is an inbuilt property of ASP.Net MVC which verifies two things: 1. Whether the Form values are bound to the Model. 2. All the validations specified inside Model class using Data annotations have been passed.


2 Answers

Referring to https://github.com/react-hook-form/react-hook-form/issues/2147

You need to set the mode to onChange or onBlur

const { register, handleSubmit, formState: { errors, isDirty, isValid }} = useForm({ mode: 'onChange' });

In this case, the 'isValid' will work as expected.

like image 141
Mohamed Ibrahim Avatar answered Oct 17 '22 23:10

Mohamed Ibrahim


The component rendered twice because of React.StrictMode.

Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions: ...

Also, in order to validate you need to submit the form (try pressing enter), if you on onChange mode without using a reference, you should use triggerValidation instead.

export default function App() {
  const {
    register,
    formState,
    watch,
    errors,
    setValue,
    handleSubmit
  }: UseFormMethods<FormValues> = useForm<FormValues>();

  useEffect(() => {
    register(
      { name: "firstName", type: "custom" },
      { required: true, min: 1, minLength: 1 }
    );
    console.log("called");
  }, [register]);

  const { isValid } = formState;
  const values = watch("firstName");

  const onSubmit = (data, e) => {
    console.log("Submit event", e);
    console.log(JSON.stringify(data));
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
          setValue("firstName", e.target.value);
        }}
      />
      {/*<button>Click</button>*/}
      <div>IsValid: {JSON.stringify(isValid)}</div>
      <div>Errors: {JSON.stringify(errors)}</div>
      <div>Form value: {JSON.stringify(values)}</div>
    </form>
  );
}

Edit old-brook-ho66h

like image 3
Dennis Vash Avatar answered Oct 17 '22 23:10

Dennis Vash