Building forms using React Hook Form



This content originally appeared on DEV Community and was authored by Dhokia Rinidh

Hey folks!

While taking my online React course, I quickly discovered something: forms are everywhere. Whether you’re buying groceries online, booking a table, signing in, paying fees, or typing questionable prompts into an AI model at 2 AM — you’re dealing with forms.

Since I wanted my portfolio to look a little less “junior developer on day 3,” I decided to learn a solid form library alongside React. The first one on my list: React Hook Form (RHF).

After going through the docs and doing a healthy amount of trial-and-error (emphasis on error), here are some useful insights I picked up. Hopefully they help you skip a few of my mistakes.

Lessons Learned (a.k.a “Things I Wish Someone Told Me Earlier”)

1. getValues() gives you a snapshot, not a subscription

getValues() returns the current form data at the exact moment you call it.

Use it in:

  • event handlers
  • async functions
  • useEffect() callbacks
  • anywhere that gets triggered by something happening

Just don’t expect it to magically stay updated. It’s a snapshot, not a live feed.

2. watch() gives you real-time updates

If you need a piece of form data that always stays in sync, use watch().

It re-renders your component whenever those watched fields change. Perfect for features like:

  • showing live previews
  • enabling/disabling buttons
  • updating UI based on input

Just remember: watching many fields can cause extra re-renders, so use it intentionally.

3. Handling errors the proper way

Form errors can be accessed in two main ways:

  • by inspecting formState.errors
  • by using the second callback of handleSubmit(onValid, onError)

Both are useful, depending on whether you want to react to errors during submission or check them after validation.

4. Custom validators can be stacked (and async!)

When using the validate option inside register():

validate: {
  validator1: value => value.length > 3 || 'Must be longer than 3 characters',
  validator2: async value => await checkUsername(value)
}

You can:

  • define multiple validator functions
  • return true (valid) or a string (error message)
  • even write async validators that call APIs or servers

RHF will run them all and aggregate the results.

5. reset() behavior depends on whether defaultValues exists

If you did not pass defaultValues to useForm(), then calling:

reset({firstName: "John" })

will update both the current values and the internal “default values”.

If you did specify defaultValues, you can still override them by intentionally passing the values option:

reset({
  values: { firstName: "John" }
})

This makes that object the new default state of your form.

Final Thoughts

These are just a few tips that helped me understand React Hook Form better as a beginner. The library is incredibly lightweight, ergonomic, and fast — once you understand what each function is doing behind the scenes.

If you spot anything interesting or want to add your own insights, feel free to drop a comment. And don’t worry, more posts are on the way (yes, even the embarrassing discoveries).

Thanks for reading — and happy form-building!


This content originally appeared on DEV Community and was authored by Dhokia Rinidh