React form validation with React Hook Form and Yup
Tags: javascript, react, frontend
Published: 2021-06-30 17:33:44

Validating user input on forms prior to submission, in my opinion, is one of the most important and fundamental things about a website these days.

Thank god we have several options to validate them, in the React ecosystem there are lots of libraries. However many of these libraries either end up having a huge boilerplate, which is sometimes scary, even when implementing in a form with few fields. Or they decrease application performance.

Keeping these points in mind, I always end up looking for a solution that is simple, with little boilerplate and that has a great performance.

Apart from that, another thing I'm looking for is a form validation library that lets you use a library to validate schemas, such as Joi, Yup, etc. This way I can reuse the schema code in the frontend and backend.

It's exactly for all these reasons that I love working with React Hook Form.

# Let's code

First we will add the following dependencies to our React application:

```
npm install react-hook-form @hookform/resolvers yup
```

Now let's pretend this is your form:

```js
import React from "react";

const App = () => {
  return (
    <form>
      <h2>Lets sign you in.</h2>
      <br />

      <input placeholder="email" type="email" required />
      <br />

      <input
        placeholder="password"
        type="password"
        required
      />
      <br />

      <button type="submit">Sign in</button>
    </form>
  );
};

export default App;
```

Now let's import `React Hook Form` into our project:

```js
import React from "react";
import { useForm } from "react-hook-form";
// Hidden for simplicity
```

Then let's get the following things from the `useForm()` hook:

```js
const App = () => {
  const { register, handleSubmit, formState: { errors }, reset } = useForm();
  return (
    // Hidden for simplicity
};
```

### Quick overview

- The `register()` method allows registering an element and applying the appropriate validation rules.
- The `handleSubmit()` function will receive the form data if validation is successful.
- The `reset()` function will clear all form fields or reset to initial values.
- In this case, we are using `formState` to return form errors in an easier way.

Now we have to import Yup into our project and then let's create our schema.

```js
// Hidden for simplicity
import * as yup from "yup";

const schema = yup.object().shape({
  email: yup.string().email().required(),
  password: yup.string().min(8).max(32).required(),
});
```

Now we have to import `@hookform/resolvers` so we can use our Yup schema to validate input values. Like this:

```js
import { yupResolver } from "@hookform/resolvers/yup";

// Hidden for simplicity

const App = () => {
  const { register, handleSubmit, formState: { errors }, reset } = useForm({
    resolver: yupResolver(schema),
  });
  return (
    // Hidden for simplicity
};
```

Now we have to create our function to submit the data (which in this example will be a simple log). Just like we're going to add the `reset()` method inside our function so that form inputs are cleared as soon as they're submitted.

Lastly let's add the `handleSubmit()` method to our form. Similar to this:

```js
const App = () => {
  const { register, handleSubmit, formState: { errors }, reset } = useForm({
    resolver: yupResolver(schema),
  });
  const onSubmitHandler = (data) => {
    console.log({ data });
    reset();
  };
  return (
    <form onSubmit={handleSubmit(onSubmitHandler)}>
      // Hidden for simplicity
    </form>
};
```

The next step is to register our inputs, assigning their names according to the properties of our schema:

```js
const App = () => {
  // Hidden for simplicity
  return (
    <form onSubmit={handleSubmit(onSubmitHandler)}>
      <h2>Lets sign you in.</h2>
      <br />

      <input {...register("email")} placeholder="email" type="email" required />
      <br />

      <input
        {...register("password")}
        placeholder="password"
        type="password"
        required
      />
      <br />

      <button type="submit">Sign in</button>
    </form>
  );
};
```

Last but not least, let's add the error messages for each of the inputs:

```js
const App = () => {
  // Hidden for simplicity
  return (
    <form onSubmit={handleSubmit(onSubmitHandler)}>
      <h2>Lets sign you in.</h2>
      <br />

      <input {...register("email")} placeholder="email" type="email" required />
      <p>{errors.email?.message}</p>
      <br />

      <input
        {...register("password")}
        placeholder="password"
        type="password"
        required
      />
      <p>{errors.password?.message}</p>
      <br />

      <button type="submit">Sign in</button>
    </form>
  );
};
```

Now with everything finished, the code should look like this:

```js
import React from "react";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";

const schema = yup.object().shape({
  email: yup.string().email().required(),
  password: yup.string().min(8).max(32).required(),
});

const App = () => {
  const { register, handleSubmit, formState: { errors }, reset } = useForm({
    resolver: yupResolver(schema),
  });
  const onSubmitHandler = (data) => {
    console.log({ data });
    reset();
  };
  return (
    <form onSubmit={handleSubmit(onSubmitHandler)}>
      <h2>Lets sign you in.</h2>
      <br />

      <input {...register("email")} placeholder="email" type="email" required />
      <p>{errors.email?.message}</p>
      <br />

      <input
        {...register("password")}
        placeholder="password"
        type="password"
        required
      />
      <p>{errors.password?.message}</p>
      <br />

      <button type="submit">Sign in</button>
    </form>
  );
};

export default App;
```

In order for you to have an idea of the final result, you should have something similar to what you see in the gif:

![result](https://res.cloudinary.com/dj5iihhqv/image/upload/v1624804450/Kapture_2021-06-27_at_15.31.42-min_m2cd7q.gif)

# What about you

What library do you use to validate your forms in React?