Skip to content

FAQs

frequently asked question.

Performance of React Hook Form

Performance is one of the primary goals for building this custom hook. React Hook Form relies on uncontrolled component, hence the reason why the register function capture the ref. This approach will reduce the amount of re-rendering occurring due to user typing or value changing. Components mount to the page is much quicker as well because they are not controlled. For mounting speed, I have completed a quick comparison test which you can refer to by this repo link.


How to create an accessible input error and message?

React Hook Form is focusing on Uncontrolled Component, which gives you the ability to build an accessible custom form easily.

import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, formState: { errors } } = useForm();
  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label htmlFor="firstName">First name</label>
      <input
        id="firstName"
        aria-invalid={errors.firstName ? "true" : "false"}
        {...register('firstName', { required: true })}
      />
      {errors.firstName && (
        <span role="alert">
          This field is required
        </span>
      )}

      <input type="submit" />
    </form>
  );
}

Does it work with Class Components?

No, not out of box. but you can build a wrapper around it and use in your Class Component.

You can’t use Hooks inside of a class component, but you can definitely mix classes and function components with Hooks in a single tree. Whether a component is a class or a function that uses Hooks is an implementation detail of that component. In the longer term, we expect Hooks to be the primary way people write React components.

How to reset the form?

There are two methods to clear the form.

  • HTMLFormElement.reset()

    This method does the same thing as clicking a form's reset button, and only clearsinput/select/checkbox values.

  • React Hook Form API: reset()

    React Hook Form's reset method will reset all fields value, and also will clear all errors within the form.


How to initialize form values?

React Hook Form relies on uncontrolled component. With an uncontrolled component, you can specify a defaultValue or defaultChecked to an individual field. However, the hook itself does provide an easier way to initialise all input values too. Example below:

import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit } = useForm({
    defaultValues: {
      firstName: "bill",
      lastName: "luo",
      email: "bluebill1049@hotmail.com"
    }
  });
  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("firstName")} />
      <input {...register("lastName")} />
      <input {...register("email")} />

      <button type="submit">Submit</button>
    </form>
  );
}

How to share ref usage?

React Hook Form needs ref to collect the input value, however, you may want to use ref for other purposes (eg. scroll into the view).

import React, { useRef } from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit } = useForm();
  const firstNameRef = useRef(null);
  const onSubmit = data => console.log(data);
  const { ref, ...rest } = register('firstName');

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...rest} name="firstName" ref={(e) => {
        ref(e)
        firstNameRef.current = e // you can still assign to ref
      }} />

      <button>Submit</button>
    </form>
  );
}import React, { useRef } from "react";
import { useForm } from "react-hook-form";

type Inputs = {
  firstName: string,
  lastName: string,
};

export default function App() {
  const { register, handleSubmit } = useForm<Inputs>();
  const firstNameRef = useRef<HTMLInputElement | null>(null);
  const onSubmit = data => console.log(data);
  const { ref, ...rest } = register('firstName');

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...rest} name="firstName" ref={(e) => {
        ref(e)
        firstNameRef.current = e // you can still assign to ref
      }} />

      <button>Submit</button>
    </form>
  );
}

What if you don't have access to ref?

You can actually register an input without a ref. In fact, you can manually setValue, setError and trigger.

Note: Because ref has not been registered, React Hook Form won't be able to register event listeners to the inputs. This means you will have to manually update value and error.

import React, { useEffect } from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, setValue, setError } = useForm();
  const onSubmit = data => console.log(data);

  useEffect(() => {
    register("firstName", { required: true });
    register("lastName");
  }, []);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        name="firstName"
        onChange={e => setValue("firstName", e.target.value)}
      />
      <input
        name="lastName"
        onChange={e => {
          const value = e.target.value;
          if (value === "test") {
            setError("lastName", "notMatch")
          } else {
            setValue("lastName", e.target.value)
          }
        }}
      />
      <button>Submit</button>
    </form>
  );
}

Browser Support?

React Hook Form support all major browsers.

For legacy IE11 support, you can import react-hook-form IE 11 version.

import { useForm } from 'react-hook-form/dist/index.ie11'; // V6
import { useForm } from 'react-hook-form/dist/react-hook-form.ie11'; // V5'
// Resolvers
import { yupResolver } from '@hookform/resolvers/dist/ie11/yup';

Why is first keystroke is not working?

Double check if you are using value instead of defaultValue.

React Hook Form is built based on uncontrolled input, which means you don't need to change input value via state by onChange. Hence you don't need value at all, in fact, you only need defaultValue for initial input value.


Testing failed due to MutationObserver?

If you have difficulty during testing and the issue was caused by MutationObserver. Make sure you install mutationobserver and import this package in your test setup.js file.


React Hook Form, Formik or Redux Form?

First of all, all libs try to solve the same problem which is making form building experience easy and great. However, there are some fundamental differences between the three, react-hook-form is built with uncontrolled input in mind and tries to provide your form with best performance and least re-render if possible. On top of that, react-hook-form is built by React Hook and used as hook, which means there is no Component for you to import. Here are some of the detail differences:

React Hook Form

Formik

Redux Form

Componentuncontrolled & controlledcontrolledcontrolled
Renderingminimum re-renderre-render according to local state changes which means as you type in the input.re-render according to state management lib (Redux) changes which means as you type in the input.
APIHooksComponent (RenderProps, Form, Field) + HooksComponent (RenderProps, Form, Field)
Package sizeSmall
react-hook-form@4.0.0
6.2KB
Medium
formik@2.0.1
14.4KB
Large
redux-form@8.2.6
27KB
ValidationBuilt-in & YupBuild yourself or YupBuild yourself or Plugins
Learning curveLowMediumMedium
StatusMedium Community: New lib and growingLarge Community: Well established form lib in the communityLarge Community: Well established form lib in the community

Can it work with Controlled component?

Short answer: Yes

React-hook-form is not recommending you to build form controlled, however you can still achieve that easily.

The trick to using watch API to monitor each input's change and assign to value prop.

Alternatively, you can use our wrapper component title="React Hook Form Controller Controller which take care those custom register for you.

import React from "react";
import { useForm, Controller } from "react-hook-form";

function App() {
  const { control } = useForm();
  
  return (
    <Controller
      render={({ field }) => <input {...field} />}
      name="firstName"
      control={control}
      defaultValue=""
    />
  );
}
import React, { useEffect } from "react";
import { useForm } from "react-hook-form";

function App() {
  const { register, watch, setValue, handleSubmit } = useForm({
    defaultValues: {
      firstName: "",
      lastName: ""
    }
  });
  const { firstName, lastName } = watch();

  useEffect(() => {
    register("firstName");
    register("lastName");
  }, [register]);

  const handleChange = (e, name) => {
    setValue(name, e.target.value);
  };

  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        onChange={(e) => handleChange(e, "firstName")}
        value={firstName}
      />

      <input onChange={(e) => handleChange(e, "lastName")} value={lastName} />
      <input type="submit" />
    </form>
  );
}

Testing React Hook Form

  • Why am I getting act warning?

    All validation methods in React Hook Form will be treated as async functions, so it's important to wrap async around your act.

  • Why input change is not fire event?

    React Hook Form using input event for input change, so to fix it. you can easily switch to fireEvent.input for react-testing-library

Нам нужна важа поддержка

Если React Hook Form была полезна в вашем React проекте, пожалуйста, поддержите проект и разработчиков звездой ❤

Edit