Creating Robust Front-End Validation using react-hooks-form 👑
Published: 2023-03-30 08:50:44

## Why Frontend validation ?

Sometimes I wonder why we bother to make validation on the frontend side when there is a bunch of it on the backend side 🤔. Reflecting on managing several frontend projects here is the key takeaway :

### 1. Saving Time and Resources

By doing front end validation we could reduce the time taken by network request. Moreover, we are also saving back end resources as we reduce the number of invalid requests from the front end.

### 2. Better User Experience

Frontend validation could improve the user experience by providing instant feedback when they make an error. This way user could correct their errors in real-time which increases their engagement with our application.

### 3. Increase security and data consistency

Backend validation wasn’t bullet proof, sometimes human error happen and we forgot some validation and our data become inconsistent (such as unusual email, or phone number format). Therefore, having the 2nd layer protection was definitely better than only one layer. Moreover, front end validation decrease security issue to some extends (such as SQL injection, XSS, etc). 


## Why use react-hooks-form ?

The reason was quite clear from the official website *“Performant, flexible and extensible forms with easy-to-use validation. - [**react-hook-form.com**](https://react-hook-form.com/)”* 🤩*.* personally, I used react hooks form because of:

- **Isolate re-render:** optimizing react rendering could be overwhelming for beginner - intermediate developers. React hooks form helps to mitigate those issue in the form, it makes sure every field only render when they are being edited.
- **Consistent Validation Strategy:** react hooks form provides a structured way of doing validation. Hence, every developer would use the same validation strategy.
- **Developer Experience:** this library provides intuitive API that could be used seamlessly across React and React Native environments.

## Built-in validation in react-hooks-form
Let's dive into the code. Assume that we want to create a form for pre-ordering sandwiches. Here's the basic code: 
{% embed https://github.com/peterchu999/hooks-validation-article %}

The code above is basic and not yet integrated with `react-hook-form`. To integrate, we need to install `react-hook-form` by running:

```jsx
yarn add react-hook-form
```

Next, we need to call the `useForm` hook:

```jsx
const {register, handleSubmit, formState: { errors } } = useForm()
```

`useForm` returns several functions, but for our demonstration, we will focus on the following essential ones:

- `register`: this function binds our input data to `useForm`. We need to specify the input `name` in the `register` function, and optionally, we can pass validation rules.
- `handleSubmit`: this function binds our form's submit behavior, it takes 2 functions as parameter:
    - `onSuccess`: the callback function that receives all data from registered fields. This function is triggered only when the data passes validation.
    - `onError`: the callback function that captures validation errors for all registered fields. This function is triggered only when validation fails.
- `formState.errors`: this state contains the error messages from our fields' validation.

Now, register our fields with `register` function then bind our form `onSubmit` with `handleSubmit:`

```jsx
<form onSubmit={handleSubmit(
          (data) => {
            console.log("successfully submit", data)
          },
          (error) => {
            console.log("some validation had failed", error)
          }
        )}
 >
...
<label>Name</label>
<input {...register("name")} />
...
<label>Email</label>
<input {...register("email")}/>
...
<label>Phone Number</label>
<input {...register("phone-number")}/>
...
<label>Sandwich Qty</label>
<input {...register("qty")}/>
...
```

So far, we have integrated the react-hook-form into our project 😎. For the final step in this section, let's set up field validation and display an error message when a field fails validation.

 to add `rules` (validation) to the fields we could pass the `RegisterConfiguration` object as the 2nd parameter to the `register` function :

```jsx
...
<div style={{ display: 'flex', width: '50%', flexDirection: 'column', }} >
	<div style={{ display: 'flex', flex: 1, justifyContent: 'space-between', }} > 
			<label>Name</label>
			<input {...register('name', 
			{ 
              required: 'name is required', 
              minLength: {
              value: 3, 
              message: 'name should have minimum 3 characther'
			} 
			})} /> 
	</div> 
	{errors.name && <p style={{ color: 'red' }}>{errors.name.message}</p>} 
</div>
...
```

The code above indicates that the `name` field is **required** and **must have a minimum of 3 characters**. If the validation fails, an error message will appear stating that either `name is required` or `name should have a minimum of 3 characters`.

the validation rules quite vary, here is the list:

- `maxLength`: validate the value of the field to have a maximum character length of x
- `minLength`: validate the value of the field to have a minimum character length of x
- `max`: validate the fields with number type to had max value of x
- `max`: validate the fields with number type to had min value of x
- `pattern`: validate the value of the field to match the Regex pattern
- `validate`: validate the value of the field to pass the custom-made function

Here is the demonstration of validating `email` fields with custom made function to make sure it contains `@dev.to` value:

```jsx
<input {...register('email', 
		{ required: 'email fields are required', 
			validate: (value) => { 
					if (!value.includes('@dev.to')) {
							 return 'need to use dev to email'; 
					} return true; 
}, })} />
```

the latest code that implements build-in validation of react-hook-form could be found on `build-in-validate` branch



## Robust validation in react-hooks-form

This method of creating validation using react-hook-form is concise and helps us organize our validation more efficiently 👀. However, there is a more robust approach to validation in react-hook-form that involves using `resolvers` (validation resolvers). `Resolvers` is an adapter that integrates react-hook-form with 3rd-party validation libraries such as `class-validator`, `joi`, `zod`, etc. By delegating the validation to these libraries, we can have a more robust validation in our apps 🔥.

Suppose we choose `class-validator` as our validation library. To install `class-validator` and `resolver`, run the following command:

```
yarn add @hookform/resolvers class-transformer class-validator
```

Then, create a `class-validator` schema:

```
export class SandwichPO {
  @MinLength(5)
  name: string;

  @IsEmail()
  email: string;

  @IsPhoneNumber()
  phoneNumber: string;

  @IsNumber()
  qty: string;
}

```

Using this schema, we can create resolvers and bind them to our `useForm` hooks:

```
const resolver = classValidatorResolver(SandwichPO);

...
const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({ resolver: resolver });
...

```

That's it! Everything is now aligned 🥳. Delegating our validation to a 3rd-party library makes our code more organized and robust 🤟.

latest code from resolver implementation could be found on `resolver-implementation` branch

## Choosing validation library
When it comes to choosing a library, there are several factors that need to be considered. The rule of thumb that I follow is:

### Experience
    
When selecting a validation library, it is best to choose one that you have used before. This will reduce the learning curve and make implementation easier.
    
### Compatibility with the backend
    
Building backend services with JavaScript has become quite common nowadays. It would be ideal to use the same validation library on both the front-end and back end to ensure consistent validation using the same schema.
    
### Library size
    
Keep in mind that the size of the validation library can increase the size of your app and cause longer download times for the user. Therefore, choose a library size that is appropriate for your needs.

## Summary; TLDR

Front-end validation could improve user experience, increase security, save resources, and maintain data consistency. Therefore, it’s crucial to have a robust validation mechanism. react-hook-form could help us to standardize our validation strategy and it could even help us to integrate a 3rd-party validation library using the react-hook-form resolvers.


**credits:**
- Photo by Antonio Borriello: https://www.pexels.com/photo/photo-of-macbook-air-on-a-table-next-to-house-plant-and-picture-frame-1297611/
- Notion AI: https://www.notion.so/product/ai

**Source:**
- https://react-hook-form.com/
- https://github.com/react-hook-form/resolvers
- https://github.com/peterchu999/hooks-validation-article