Forms Library — react-hook-form

Less Re-Rendering, Cleaner Code

Forms Library — react-hook-form

For anything beyond a tiny form, `react-hook-form` saves re-renders and reads cleaner than hand-rolled controlled state.

4 min read Level 2/5 #react#forms#react-hook-form
What you'll learn
  • Set up a basic form with `react-hook-form`
  • Validate inputs
  • Recognize when the library is worth it

For tiny forms, controlled useState is fine (chapter 3). For anything bigger — many fields, async validation, complex shapes — react-hook-form is what most teams use.

Install

npm install react-hook-form

A Basic Form

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

function Signup() {
  const { register, handleSubmit, formState: { errors } } = useForm();

  function onSubmit(data) {
    console.log("submit", data);
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("name", { required: "Name is required" })} />
      {errors.name && <p>{errors.name.message}</p>}

      <input
        type="email"
        {...register("email", {
          required: "Email is required",
          pattern: { value: /^\S+@\S+\.\S+$/, message: "Invalid email" }
        })}
      />
      {errors.email && <p>{errors.email.message}</p>}

      <button>Sign up</button>
    </form>
  );
}

Why It’s Nicer

  • No re-render on every keystroke — the library uses uncontrolled refs internally
  • Validation declarations live with the fields
  • Error messages and dirty/touched states for free
  • Easy integration with schema validators (Zod, Yup)

With a Schema (Zod)

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";

const schema = z.object({
  name: z.string().min(1, "Name is required"),
  email: z.string().email("Invalid email"),
  age: z.coerce.number().min(18, "Must be 18+"),
});

function Signup() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(schema),
  });
  // ... same as before
}

The schema is the single source of truth for shape AND validation.

When To Skip

For one input or two, useState is fine. The library shines when you have a handful of fields, mixed validation rules, and want clean code at the call site.

Up Next

How to write tests.

Testing →