Skip to content

React Hook Form

Performant, flexible and extensible forms with easy-to-use validation.

React Web

React Native

Features

</>

DX

Intuitive, feature-complete API providing a seamless experience to developers when building forms.

HTML standard

HTML standard

Leverage existing HTML markup and validate your forms with our constraint-based validation API.

Super Light

Super Light

Performance is important and package size matters. React Hook Form is a tiny library without any dependencies.

Performance

Performance

Minimizes the number of re-renders and faster mounting, striving to provide the best user experience.

Adoptable

Adoptable

Since form state is inherently local, it can be easily adopted without other dependencies.

Library Code Comparison

Reducing the amount of code that you have to write is one of the primary goals for React Hook Form. To illustrate that, let's look at a very simple form of validation among some of the most popular form validation libraries.

⚠ Note: Both Formik and Redux-Form code below are copied from official documentation.

Formik

import React from "react";
import { Formik, Form, Field } from "formik";

function validateEmail(value) {
  let error;
  
  if (!value) {
    error = "Required";
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)) {
    error = "Invalid email address";
  }
  
  return error;
}

function validateUsername(value) {
  let error;
  
  if (value === "admin") {
    error = "Nice try!";
  }
  
  return error;
}

const Example = () => {
  const onSubmit = values => {
    console.log(values);
  };

  return (
    <Formik
      initialValues={{
        username: "",
        email: ""
      }}
      onSubmit={onSubmit}
    >
      {({ errors, touched }) => (
        <Form>
          <Field name="email" validate={validateEmail} />
          {errors.email && touched.email && errors.email}

          <Field name="username" validate={validateUsername} />
          {errors.username && touched.username && errors.username}

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

React Hook Form

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

const Example = () => {
  const { handleSubmit, register, errors } = useForm();
  const onSubmit = values => {
    console.log(values);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        name="email"
        ref={register({
          required: 'Required',
          pattern: {
            value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
            message: "invalid email address"
          }
        })}
      />
      {errors.email && errors.email.message}

      <input
        name="username"
        ref={register({
          validate: value => value !== "admin" || "Nice try!"
        })}
      />
      {errors.username && errors.username.message}

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

Redux Form

import React from "react";
import { Provider } from "react-redux";
import { Field, reduxForm } from "redux-form";
import store from "./store";

const validate = values => {
  const errors = {};

  if (!values.username) {
    errors.username = "Required";
  } else if (values.username.length !== "admin") {
    errors.username = "Nice try!";
  }

  if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
    errors.email = "Invalid email address";
  }

  return errors;
};

const renderField = ({ input, label, type, meta: { touched, error } }) => (
  <>
    <input {...input} placeholder={label} type={type} />
    {touched && error && <span>{error}</span>}
  </>
);

const Form = props => {
  const { handleSubmit } = props;
  const onSubmit = values => {
    console.log(values);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Field name="email" type="email" component={renderField} label="Email" />
      <Field name="username" component={renderField} label="Username" />
    
      <button type="submit">Submit</button>
    </form>
  );
};

const FormRedux = reduxForm({ form: "syncValidation", validate })(Example);

const Example = () => (
  <Provider store={store}>
    <Example/>
  </Provider>
);

Isolate Component Re-render

You have the ability to isolate components re-render which lead to less performance impact on your page or app. The following example demonstrate such behaviour.

Note: Type in the input box to see the render behaviour.

React Hook Form

Child Component A
Child Component B
Child Component C

VS

Controlled Form

Child Component A
Child Component B
Child Component C

Reduce Rendering

Do you ever wonder how many component re-renders have been triggered by the user? React Hook Form embraces uncontrolled form validation to reduce unnecessary performance impact.

Total re-renders: 30+

Total re-renders: 3

Total re-renders: 30+

Faster Mounting

The following results demonstrate how long it took to render and mount the components. Results are captured under a 6x CPU slow down on App start with the Chrome Dev Tools' performance tab. The running code is from the section above Library Code Comparison.

React Hook Form

  • No. of mount(s): 1
  • No. of committing change(s): 1
  • Total time: 1800ms
React Hook Form performance

Formik

  • No. of mount(s): 6
  • No. of committing change(s): 1
  • Total time: 2070ms
Formik performance

Redux Form

  • No. of mount(s): 17
  • No. of committing change(s): 2
  • Total time: 2380ms
Redux Form performance

Want to see more intense performance tests? Check out the result of 1000 fields within a form here.

Live Demo

The following form demonstrates form validation in action. Each column represents what has been captured in the custom hook. You can also change fields in the form by clicking the EDIT button.

Example

or

Watch

Change input value to see watched values

{}

Errors

Validation errors will appear here

Touched

Touched fields will display here

[]

Find it useful and interesting?

Form validation should be much simpler. React Hook Form will lead you to write less code and have better performance. Check out the Get Started section and learn more on the API documentation page.