React Hook Form

Viraj NikamViraj Nikam
3 min read

Lesson 1: Story behind.

Before I discovered React Hook Form, I realized I was a complete noob when it came to handling form data in React. I used to manage form state and validations using local state variables. While this approach works for simple forms, it quickly becomes messy and hard to scale as your form grows.

To make things more maintainable, I thought of lifting the state to a global level using something like Context API or even a state management library like Redux or Zustand. But that also felt like overkill for just managing form inputs and validations.

Lesson 2: Introduction.

React Hook Form is a lightweight library which uses react hooks to manage the form state and validations. It fits right into your existing react component structure, making it easy to build and manage forms without a lot of extra code.

Lesson 3: let's write and understand the code.

Managing form state usually means keeping track of local state with the useState hook, context api or any other state management library like redux or zustand. React hook form takes care of this by providing you its own context api.

import {useForm, FormProvider} from 'react-hook-form';


const ReactHookFormExample = ()=>{

  const rfhMethods = useForm({
    defaultValues : {
            name: "Jhon doe"
            mobile : 4523652145
        }
    });

  const {register, reset, handelSubmit, formState:{errors}} = rfhMethods;

  const onSubmit = (formData)=>{
    console.log(formData, "FORM_DATA");
    reset();
  }


return (
    <FormProvider {...rfhMethods}>
       <form>
            <div className='user-name'>
                <input type="text" {...register("name")} />
                 {errors.name && <span>{errors.name.message}</span>}
            </div>
            <div className='user-mobile'>
                 <input type="number" {...register("mobile")}>
                  {errors.mobile && <span>{errors.mobile.message}</span>}
            </div>
       </form>
    </FormProvider>
        )
}

In the above example, useForm provides several methods & properties to manage the form:

  1. register : a function to register the fields.

  2. handelSubmit : a function to handel the form submission.

  3. formState : its an object containing the form state with validation errors.

FormProvider is the context provider given to us by react hook form, to handel the form state in the nested components. eg:

const {useFormContext} from 'react-hook-form';

const nestedChildComponent = ()=>{
    const {register} = useFormContext();

return (
        <div className='user-city'>
            <select {...register("city")}>
                <option value='pune'>Pune</option>
                <option value='amdabad'>Amdabad</option>
                <option value='mumbai'>Mumbai</option>
            </select>
        </div>
       )
}

Here, with the useFormContext method you can access all the methods that useForm provides.

Lesson 4 : Traditional Forms in React – Why It's a Struggle

When you're building forms using plain React (also called "traditional forms"), things can quickly get messy. You have to manually handle every input, track changes, validate data, and manage errors — all by yourself. It may sound simple at first, but even a basic form can turn into a lot of boilerplate code.

import React, {useState} from "react";

export default const TraditionalForms = ()=>{
    const [formData, setFormData] = useState({name:"", email:""});
    const [errors, setErrors] = useState({});

    const handelInputChange = (evt)=>{
        const {name, value} = evt?.target;
            setFormData((prev)=>({...prev, [name]: value}))
     }

    const onSubmit = (evt)=>{
        evt.preventDefault();

        const errors = {};
        if(formData.name?.length < 2) errors.name = "name should contain atlist 2 characters";
        if(!/\S+@\S+\.\S+/.test(formData.email)) errors.email = "enter valid email";

        setErrors(errors);

        if(Object.keys(errors).length===0){
            console.log("FORM_DATA", formData);
          }

    };


    return (
        <form onSubmit={onSubmit}>
            <input type='text' name='name' value={formData.name} onChange={handelInputChange} />
            {errors?.name && <span>{errors.name}</span>}

            <input type='email' name='email' value={formData.email} onChange={handelInputChange} />
            {errors?.email && <span>{errors.email}</span>}

            <button type='submit'> Submit </button> //type : "submit" | "button" | "reset" by default to submit
        </form>
           )

If you're just starting out, building forms manually is a great way to learn. But as your project grows, you'll definitely want to use a form library to avoid drowning in state management and validation logic.

Traditional forms teach you the basics — but modern form libraries help you move faster and write cleaner code.

0
Subscribe to my newsletter

Read articles from Viraj Nikam directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Viraj Nikam
Viraj Nikam