Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Validating Forms with React Hook Form

Forms with React Hook Form

~11 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

Our ReviewForm.jsx from the last chapter works, but with larger forms (many fields, more complex rules) the manual approach quickly becomes repetitive. React Hook Form is by far the most popular library for automating this.

Installation

npm install react-hook-form

Why React Hook Form (and not just more custom code)?

  • Fewer re-renders: React Hook Form tracks field values internally via uncontrolled references (see chapter 13) instead of useState per keystroke – noticeably faster on large forms.
  • Built-in validation rules: "required", "minLength", custom validator functions – without writing every rule yourself.
  • Less code: no useState per field, no manual onChange handling.

Rebuilding ReviewForm.jsx

Replace the entire content of src/components/ReviewForm.jsx:

src/components/ReviewForm.jsx
import { useForm } from 'react-hook-form';

function ReviewForm({ onSubmitReview }) {
  const {
    register,
    handleSubmit,
    reset,
    formState: { errors },
  } = useForm({
    defaultValues: { name: '', rating: 5, comment: '' },
  });

  function onValid(values) {
    onSubmitReview(values);
    reset();
  }

  return (
    <form onSubmit={handleSubmit(onValid)} className="review-form">
      <div className="form-field">
        <label htmlFor="name">Name</label>
        <input
          id="name"
          {...register('name', { required: 'Please enter your name.' })}
        />
        {errors.name && <p className="form-error">{errors.name.message}</p>}
      </div>

      <div className="form-field">
        <label htmlFor="rating">Rating</label>
        <select id="rating" {...register('rating')}>
          {[5, 4, 3, 2, 1].map((star) => (
            <option key={star} value={star}>{star} {star === 1 ? 'star' : 'stars'}</option>
          ))}
        </select>
      </div>

      <div className="form-field">
        <label htmlFor="comment">Comment</label>
        <textarea
          id="comment"
          {...register('comment', {
            minLength: { value: 10, message: 'The comment must be at least 10 characters long.' },
          })}
        />
        {errors.comment && <p className="form-error">{errors.comment.message}</p>}
      </div>

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

export default ReviewForm;

Understanding register(): the heart of the library

{{...register('name', {{ required: '...' }})}} is the central idea: register() returns an object with exactly the props an <input> needs to register itself with React Hook Form (among others name, onChange, onBlur, ref) – the spread operator {{...register(...)}} passes all of these through automatically as props, without you having to write them out one by one.

formState: {{ errors }} automatically holds the matching error messages per field name after a failed validation attempt – errors.name.message is exactly the string you passed to required.

Chapter 14 (manual)React Hook Form
useState per field + a custom validate() functionregister('fieldname', {{ rules }}) handles state AND validation
Write an onChange handler manually for each fieldwired automatically via register()
Call event.preventDefault() manuallyhandleSubmit(onValid) handles this automatically, only calls onValid with VALID data

Tipp: Both approaches – manual validation and React Hook Form – are valid, common patterns in real projects. Small, simple forms (one or two fields) are often just as fast written manually; once a form grows, React Hook Form pays off noticeably.