How to Validate Forms with React Hook Form in React Apps
Tags: javascript, webdev, react, beginners
Published: 2022-04-02 00:38:26

Validating inputs from forms is very important to keep a clean and organized backend service. If you have to write a program that validates and handles form input based on different cases, this can be a difficult task. But with React Hook Form, we worry less about how to handle errors from web forms.

<a href="https://react-hook-form.com" target="_blank" rel="noopener noreferrer">React Hook Form</a> is a library that enables us to accept only valid data from the user. With React Hook Form, we can create performant React forms, which validate form inputs and make sure they are in the exact format required by the server.

In this tutorial, I will guide you through the process of validating data from your React forms using React Hook Form.

### Setup a React project

- Open your terminal and run the command below to create a React app project

```shell
npx create-react-app reacthookform
```

- Install React Hook Form. After installing React Hook Form, skip to the next section if you're not using Tailwind CSS.

```shell
npm install react-hook-form
```

- Optional: Install Tailwind CSS by running the command below. Tailwind CSS is utility-first CSS framework for building mordern user interfaces.

```shell
  npm install -D tailwindcss postcss autoprefixer
```

- Generate tailwind.config.js and postcss.config.js configuration files by running:

```shell
npx tailwindcss init -p
```

- Open `tailwind.config.js` and copy the code below:

```js
module.exports = {
  content: ['./src/**/*.{js,jsx,ts,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
};
```

- In the `./src/index.css` file, add Tailwind directive to your CSS:

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
{% embed https://dev.to/arshadayvid/data-fetching-in-nextjs-v121-simplified-with-use-cases-1b0g %}

### React Hook Form Validation

I will explain this concept by creating a user registration form that accepts different information from the user, such as first name, last name, age, gender, email address, and password.

A popular way to handle these inputs in React is to keep all the data in a state, but React Hook Form provides a more efficient way of handling the form data.

**Let's examine the code below:**

```jsx
import { useForm } from 'react-hook-form';

export default function Home() {
  const { register, handleSubmit } = useForm();

  const submitForm = (data) => {
    console.log(data);
  };

  return (
    <div>
      <main className="flex items-center justify-center py-8 min-h-screen">
        <form
          onSubmit={handleSubmit(submitForm)}
          className="flex flex-col w-[500px] gap-4"
        >
          <label htmlFor="firstName">First Name</label>
          <input
            type="text"
            className="border-2 py-2 px-4"
            {...register('firstName')}
          />

          <label htmlFor="lastName">Last Name</label>
          <input
            type="text"
            className="border-2 py-2 px-4"
            {...register('lastName')}
          />
          <label htmlFor="age">Age</label>
          <input
            type="number"
            className="border-2 py-2 px-4"
            {...register('age')}
          />

          <select {...register('gender')} className="border-2 py-2 px-4">
            <option value="female">Female</option>
            <option value="male">Male</option>
            <option value="others">Others</option>
          </select>

          <label htmlFor="email">Email Address</label>
          <input
            type="email"
            className="border-2 py-2 px-4"
            {...register('email')}
          />

          <label htmlFor="password">Password</label>
          <input
            type="password"
            className="border-2 py-2 px-4"
            {...register('password')}
          />

          <button
            className="py-2 px-4 border bg-slate-300 hover:bg-slate-500 hover:text-slate-50"
            type="submit"
          >
            Submit
          </button>
        </form>
      </main>
    </div>
  );
}
```

> The code snippet above introduces a hook called useForm, which contains the functions `register` and `handleSubmit`.

- useForm() is a custom hook in React Form Hook used for managing forms with ease. You can find some optional arguments [here](https://react-hook-form.com/api/useform)
- register("variable_name") is a function that accepts the name of the input field as an argument. This argument represents the property name of the input field.
- handleSubmit() is function that wraps the submit function. It handles validation of the data provided by the user before sending it to the server.

#### How then can we validate the user input?

The `register()` function is used to validate form inputs. It accepts two arguments - the property name of the input field and the validation rules. A validation rule is an object containing the set of rules to be met by each input field, as well as the error messages to display when the rules are not met.

**Let's take a look at an example**
I will be using the user registration form we created earlier to explain this concept.

```jsx
import { useForm } from 'react-hook-form';

export default function Home() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();

  const submitForm = (data) => {
    console.log(data);
  };

  return (
    <div>
      <main className="flex items-center justify-center py-8 min-h-screen">
        <form
          onSubmit={handleSubmit(submitForm)}
          className="flex flex-col w-[500px] gap-4"
        >
          <label htmlFor="firstName">First Name</label>
          <input
            type="text"
            className="border-2 py-2 px-4"
            {...register('firstName', {
              required: 'Please enter your first name',
            })}
          />
          {/* --- displays error message for first name */}
          {errors?.firstName && (
            <p className="text-red-500">{errors.firstName.message}</p>
          )}

          <label htmlFor="lastName">Last Name</label>
          <input
            type="text"
            className="border-2 py-2 px-4"
            {...register('lastName', {
              required: 'Please enter your last name',
            })}
          />
          {/* --- displays error message for last name */}
          {errors?.lastName && (
            <p className="text-red-500">{errors.lastName.message}</p>
          )}

          <label htmlFor="age">Age</label>
          <input
            type="number"
            className="border-2 py-2 px-4"
            {...register('age', {
              required: 'Please enter your age',
              valueAsNumber: true,
              min: {
                value: 16,
                message: 'You must be greater than 15',
              },
            })}
          />
          {/* --- displays error message for age */}
          {errors?.age && <p className="text-red-500">{errors.age.message}</p>}

          <select
            {...register('gender', { required: 'Please provide your gender' })}
            className="border-2 py-2 px-4"
          >
            <option value="female">Female</option>
            <option value="male">Male</option>
            <option value="others">Others</option>
          </select>
          {/* --- displays error message for gender */}
          {errors?.gender && (
            <p className="text-red-500">{errors.gender.message}</p>
          )}

          <label htmlFor="email">Email Address</label>
          <input
            type="email"
            className="border-2 py-2 px-4"
            {...register('email', { required: 'Please enter a valid enail' })}
          />
          {/* ---displays error message for email */}
          {errors?.email && (
            <p className="text-red-500">{errors.email.message}</p>
          )}

          <label htmlFor="password">Password</label>
          <input
            type="password"
            className="border-2 py-2 px-4"
            {...register('password', {
              required: 'Please enter your password',
              minLength: {
                value: 8,
                message: 'Your password must contain at least 8 characters',
              },
            })}
          />
          {/* ---displays error message for password */}
          {errors?.password && (
            <p className="text-red-500">{errors.password.message}</p>
          )}

          <button
            className="py-2 px-4 border bg-slate-300 hover:bg-slate-500 hover:text-slate-50"
            type="submit"
          >
            Submit
          </button>
        </form>
      </main>
    </div>
  );
}
```

> From the code snippet above,

- I imported `formState: { errors }` - an object containing the validation rules and error messages for each of the registered form input from `useForm()`.
- The validation rule in the `register()` function has the property of `required`- meaning the form fields are important, and if they are left empty, it displays the error message - which is the value of the `required` property.
- In age, the `register()` function has the `required` property - `valueAsNumber` and `min`. `valueAsNumber` converts the user's input to a data type of Number. `min` is an object containing two keys - `value` and `message`. `value` contains the minimum value the form accepts and `message` is a custom error message you will like to show the user.
- For the password, the `register()` function has the key - `minLength` which is an object with two keys, `value` and `message`. `value` refers to the number of characters and `message` is the error message to displayed if the number of characters is not upto the required value.

### Conclusion

According to [https://react-hook-form.com](https://react-hook-form.com/), React Hook Form reduces the amount of code you need to write while removing unnecessary re-renders, so you don't have to worry about performance issues. React Hook Form optimizes the performance of your React forms. With lesser code, you can build faster and more optimized web forms.

Thank you for reading!

{% embed https://dev.to/arshadayvid %}  

### Writer's Corner
Hi, I am open to freelance technical writing gigs and remote opportunities. Let's work together.  📧: asaoludavid234@gmail.com

Feel free to connect with me on [Twitter](https://twitter.com/Arshadayvid) and [LinkedIn](https://www.linkedin.com/in/david-asaolu234/)

<img src="https://media.giphy.com/media/BYoRqTmcgzHcL9TCy1/giphy.gif"/>