skip to Main Content

React-Hook-Form Version Number

7.51.2

The issue

When using react-hook-forms useFormContext with this component:

TextInput

import { useFormContext } from "react-hook-form";
import { get } from "lodash";

export const TextInput = ({
  name,
  placeholder,
  disabled = false,
}) => {
  const { register, formState } = useFormContext();
  const field = register(name, {
    maxLength: { value: 5, message: "Too Long" },
  });

  const error = get(formState.errors, name);
  const label = error ? <label>{error.message}</label> : null;
  return (
    <div>
      <input
        data-testid={`form-input-${name}`}
        type="text"
        autoComplete="off"
        placeholder={placeholder}
        readOnly={disabled}
        {...field}
      />
      {label}
    </div>
  );
};

Properly wrapped in the Provider (the divs wrapping the inputs are styled removed it for visual clarity):

import { FormProvider, useForm } from "react-hook-form";
import { TextInput } from "./TextInput";
import { Submit } from "./Submit";


export const Form = ({ onSubmit, initialValues }) => {
  const methods = useForm({ defaultValues: initialValues });
  const submitFunction = methods.handleSubmit(onSubmit);
  return (
    <FormProvider {...methods}>
      <form onSubmit={submitFunction}>
        <div>
          <div>
            <TextInput
              name="name"
              placeholder="Name"
            />
          </div>
        </div>
        <Submit
          onClick={submitFunction}
          isFormValid={methods.formState.isValid}
        />
      </form>
    </FormProvider>
  );
};

For whatever reason the errors in formState: {errors} does not update onChange/onBlur/onFocus. Despite the formState : {isValid} updating when the validation returns invalid.

Thru my investigations I noticed that if I update the change handler to

const handleChange = async (e) => {
  await trigger(fieldName)
  await onChange(e)
}

Where onChange and trigger come from react-hook-form.
Then the errors object gets updated properly.

I have made a Code Sandbox illustrating it:

https://codesandbox.io/p/sandbox/cool-lalande-8n2kxp

Any help with getting it to work without hacking it to force the manual validation trigger, would be appreciated. Maybe the structure of what I am doing is wrong somewhere? I am honestly at a loss here.

2

Answers


  1. It’s because the default mode is onSubmit, so that error messages are only shown after the user has submitted. You’re disabling the submit button (which I might add is somewhat of a bad practice), so the error messages will never be shown to the user unless you change the mode something other than onSubmit such as:

    • onBlur
    • onChange
    • onTouched
    • all

    tl;dr – If you add mode:all to useForm() then it works

    const methods = useForm({ defaultValues: initialValues, mode: "all" });
    

    See the modified codesandbox:

    https://codesandbox.io/p/sandbox/cool-lalande-forked-xxtpd9?file=%2Fsrc%2FForm.jsx

    Login or Signup to reply.
  2. The reason is the mode. You should change it to the following

    const methods = useForm({ defaultValues: initialValues, mode: "all" });
    

    If you want to check the errors, it’s good to use watch method in the react-hook-form

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search