React Hook Form Validation

Last Updated Jun 13, 2022
Elizabeth (Lizzie) Shipton

Lizzie is a Full Stack Engineer at Udacity and freelance technical content writer. She has experience working with Node, GraphQL, Postgres, React and Sass.

Table of Contents:

React Hook Form is a relatively new library that takes advantage of React Hooks to build form components. If you aren’t using hooks in your React code yet, building form validation with them is a great way to start. Whether you’re building a progressive web app, a mobile app, or a simple online signup form, chances are you are going to need to do form validation at some point.

In this tutorial, we’ll dive briefly into React Hooks and get a feel for what they are and how they can improve your React code. Then we’ll use the React Hook Form library and the AbstractAPI phone number validator API to create a basic phone number input form with form validation.

Don't reinvent the wheel.
Abstract's APIs are production-ready now.

Abstract's suite of API's are built to save you time. You don't need to be an expert in email validation, IP geolocation, etc. Just focus on writing code that's actually valuable for your app or business, and we'll handle the rest.

Get started for free

What Are React Hooks?

Hooks were introduced in React version 16.8, in 2019. They are essentially a way of easily tapping into React state and other features without having to write a class.

Typically, managing local state in a React component meant that you had to write the component as a class. You initialized the component’s state via a call to the constructor() and then accessed any values in the state by pulling the values out of this.state

If you’re a Javascript developer, you’re probably already familiar with the pitfalls of the this keyword. Suffice it to say, using this resulted in all kinds of scope and context problems, and meant that component methods had to be explicitly bound to the parent class using bind(), which increased code verbosity and made things pretty confusing.

React Hooks allows us to write pure functional React components while also giving us the power of state and other class-based lifecycle methods. It improves code readability and optimization by removing a lot of the boilerplate that has to be written for class components. Not only that, it reduces the risk of introducing bugs due to context and scoping errors.

React Hook Form

One place where React Hooks are particularly useful is in managing the state of forms. Forms are notoriously painful to write, simply because a form requires a lot of state management. Using hooks greatly reduces the size and complexity of form components.

Getting Started

This tutorial assumes you're familiar with using React. If you're not already familiar with using React, check out the documentation to get started.

If you don’t already have a React App running on your computer, use Create React App to quickly spin one up.


$ npx create-react-app react-hook-form-validation
$ cd react-hook-form-validation
$ npm start

Head to https://localhost:3000 to check out your basic React App running in the browser.

Since hooks are included as part of React, we don’t need to install anything to make them work. However, we do need to import React Hook Form, as it's a separate library.


$ npm install --save react-hook-form

After we install React Hook Form, we're ready to start building.

Building the Component

Add a file called PhoneNumberInput.js next to App.js inside the src/ folder. This is where we’ll render our input component and add all the validation logic. 

For now, let’s just create the basic functional component and return a <div> with some text inside it.


import React from "react";
 
const PhoneNumberInput = () => {
 return (
     <div>
         <p>This is where we'll build the form</p>
     </div>
 );
};
 
export default PhoneNumberInput;

Now, go to App.js and remove all the boilerplate from between the two outermost <divs>. Import the new form component we just scaffolded and render that instead.


import './App.css';
import PhoneNumberInput from './PhoneNumberInput';
 
function App() {
 return (
   <div className="App">
     <PhoneNumberInput/>
   </div>
 );
}
 
export default App;

Go back to https://localhost:3000 and take a look at your newly rendered component.

Nice!

Adding React Hook Form

To get started with React Hook form, import the useForm hook and the form and input components. These will give us access to all the methods we need to create a basic form.


import React from "react";
import { useForm, form, input } from "react-hook-form";
 
const PhoneNumberInput = () => {
 
 const { register, handleSubmit, formState: { errors } } = useForm();
 const onSubmit = data => console.log(data);
 
 console.log(errors);
 
    return (
     <div style={{marginTop: '2rem'}}>
           <form onSubmit={handleSubmit(onSubmit)}>
               <input type="tel" placeholder="Mobile number" 
             {...register("phoneNumber", 
               {required: true, minLength: 6, maxLength: 12})
             } 
         />
               <input type="submit" />
           </form>
       </div>
 );
};
 
export default PhoneNumberInput;

Calling the useForm() hook gives us access to a register function, handleSubmit function, and our formState (which also includes our errors object.)

We use handleSubmit to call our own custom onSubmit function. All it does console.log the data from our form (this gets passed to our function by the handler.) In real life, this would send the data to our backend.

Meanwhile, register is where we can apply validation rules. By calling the register function, we are able to assign a named value to the input (we’ve chosen phoneNumber.) This is the value that will come through as the field name in our data object inside the onSubmit function.


const onSubmit = data => console.log(data); // data => {phoneNumber: “value”}

We’ve also passed some basic validation rules to the register function. For now, we’re just checking the length of the input number and making the form field required. Later, this is where we’ll perform more robust form validation using the AbstractAPI endpoint.

Right now, we’re just logging our errors, which are provided to us by the formState. Later, we will want to show an error to the user if the number the input is invalid. Notice that we’re able to call console.log right inside our component—that’s because this form is pure functional component, not a React class.

To see the validation and errors in action, go back to localhost 3000 and open the Javascript Dev Tools (cmd + opt + j) Hit the submit button while the form input is empty. You should see an object logged to the console. 

This is the error object. Expand it, and you’ll see that the type of error is “required.” React Hook Form has detected that we tried to submit a required field while it was empty, and raised an error for us.

The problem is, these errors aren’t very smart. Try typing a letter into the input, and look at the console.

We’re logging an error, but it’s the wrong kind. This is a minLength error, and while that’s technically correct (the phone number currently only contains one character) it’s not really the right type of error for what’s going on here.

We need a bit more control over our validation. Let’s create our own custom validation function and use AbstractAPI to validate the phone numbers.

Validating the Input Using Abstract API

Let’s add some more robust validation for our phone number input. 

Getting Started With the API

First, we’ll need to get started with AbstractAPI. Navigate to the Phone Number Validation API homepage, and click on the blue “Get Started” button.

If you’ve never used AbstractAPI before, you’ll be asked to create an account. If you have, you may need to log in. Once you’ve done that, you’ll land on the API dashboard. 

Copy your private API key and create a variable for it in your PhoneNumberInput file. We’ll use it later when we send the validation request to the API. Let’s also grab the URL we’ll be using and create a value for that too.


const apiKey = 'YOUR_API_KEY';
const apiURL = 'https://phonevalidation.abstractapi.com/v1/?api_key=' + apiKey;

Next, we’ll write a function to send the validation request.

Sending the Validation Request

Write a function called validatePhoneNumber inside your form component. We’ll use fetch to send the request to the validation API, and we’ll use to async/await syntax.


const validatePhoneNumber = async (phoneNumber) => {
   const fullURL = apiURL + "&phone=" + phoneNumber;
   const validationResponse = await (await fetch(fullURL)).json();
   return validationResponse.valid;
}

AbstractAPI returns a JSON response object that looks like this:


{
    "phone": "14152007986",
    "valid": true,
    "format": {
        "international": "+14152007986",
        "local": "(415) 200-7986"
    },
    "country": {
        "code": "US",
        "name": "United States",
        "prefix": "+1"
    },
    "location": "California",
    "type": "mobile",
    "carrier": "T-Mobile Usa, Inc."
}

There’s lots of useful information here, but all we need is the value of the valid field. In our validatePhoneNumber function, we’ve parsed the JSON response and returned just the boolean value of the valid field as our response from this function.

When we call this function and pass in a phone number, the result will be either true or false, depending on whether or not the phone number provided was valid.

Using the Validated Response

Now all we need to do is plug this function into our validation rules. There is an onBlur field on the options object that calls a function whenever the user navigates away from the field. The function you pass to onBlur receives an event object. We can pull the phone number out using event.target.value.


{...register("phoneNumber", {onBlur: (e) => validatePhone(e)})}

For the sake of simplicity, we’ve removed the other validation options.

Handling Errors

Let’s show a form error to the user if the phone number provided wasn’t valid. Instead of simply returning the value from our validatePhoneNumber function, we’ll use it to add an error message to our errors object.


 const validatePhone = async (phoneNumber) => {
   const fullURL = apiURL + "&phone=" + phoneNumber;
   const validationResponse = await (await fetch(fullURL)).json();
     if (validationResponse.valid) {
         errors["phoneNumber"] = null;
     } else {
         errors["phoneNumber"] = "INVALID PHONE"
   }
 }

Next, we’ll check the errors object inside our rendered component, and if it contains a phoneNumber error, we’ll show the user an error message.


    {!!errors.phoneNumber && <p style={{color: 'red'}}>{errors.phoneNumber}</p>}

Let’s try it out. Go back to localhost 3000, enter an invalid phone number into the input, and then click away from the input.

Sweet! Our request to the API went through, the API detected that the number was invalid, and we used the valid:false response to show a validation error to our user.

Conclusion

That’s all it takes to get up and running with form validation in React Hook Form. There are many ways we can improve this code. For starters, we’re not handling network errors or any other kind of error that might arise during the validation process. Secondly, we need to display a loading indicator while the request is being sent to show the user that something is happening. 

Finally, the phone input itself could be improved using a package like react-phone-number-input, which gives us proper phone number formatting and a country code dropdown right out of the box.

FAQs

What is React Hook Form?

React Hook Form is an easy-to-use library that leverages React Hooks to build performant, scalable forms. It gives us a useForm hook that provides access to components and methods for form creation and validation. React Hook Form registers form components to a React hook using a provided register method. The register method takes an object of validation options that can include out-of-the-box methods like minLength and isRequired, or can be passed a custom validation function.

How Does the AbstractAPI Phone Validator API Work?

The AbstractAPI Phone Validator API checks a phone number against a set of databases containing phone numbers from over 19 countries. No calls are made and no SMS messages are sent during the phone number validation process. You can use the service to check the validity of phone numbers, and to standardize numbers for your contact list or collect information about a number.

What Are React Hooks?

React Hooks were introduced in version 16.8, in 2019. A hook allows you to use local state without having to write a class-based component. React Hooks allow pure functional components to “hook” into state and other component lifecycle methods. They let you write clearer, more optimized, and less bug-prone React code.

Validate & verify emails instantly using Abstract's APIs.

Get started for free
Validate & verify emails instantly using Abstract's APIs.
Get started