Guides
Last updated
April 8, 2024

React Phone Number Validation with RegEx

Elizabeth (Lizzie) Shipton

Table of Contents:

Get your free
Phone Validation
API key now
4.8 from 1,863 votes
See why the best developers build on Abstract
START FOR FREE
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
No credit card required

A very simple way to validate phone numbers in React is to use Regex to parse and match the string. Although the method is very simple, it’s also not terribly robust, so as well as looking at Regex in this tutorial, we’ll also take a look at a more resilient way of validating a phone number using AbstractAPI’s free phone number validator.

Let’s send your first free
Phone Validation
call
See why the best developers build on Abstract
Get your free api

How to Validate a Phone Number Using Regex Step by Step

We’re going to use react-phone-number-input, an NPM package that provides out-of-the-box components for phone number inputs, along with some handy methods for phone number validation.

We’ll also use React Hook Form, a library that uses React Hooks to make building forms and managing form state easy.

Create a React app and Install Dependencies

We’ll assume that you already have a basic understanding of React and Create React App. If you don't, check out this tutorial on React, and this information on Create React App before proceeding. 

To spin up a new app using Create React App


$ npx create-react-app react-phone-validation-app
$ cd react-phone-validation-app

Install react-phone-number-input and react-hook-form.


$ npm install react-phone-number-input
$ npm install react-hook-form

And start the app


$ npm start

This will open a new browser window with the app running at http://localhost:3000.

Build the Input

Inside src create a new file called regex-phone-number-input.js and import your dependencies. Create a React Component called RegexPhoneNumberInput and for now, just render some text.


import React from "react";
import { useForm, Controller } from "react-hook-form";
import PhoneInput, { isValidPhoneNumber } from "react-phone-number-input";
import "react-phone-number-input/style.css";

const RegexPhoneNumberInput = () => {
return (

This is where our phone input will go



);
};
export default RegexPhoneNumberInput;

Remove the boilerplate between the two <header>s in App.js, import your new RegexPhoneNumberInput and render it instead.


import './App.css';
import PhoneNumberInput from './phone-number-input';

function App() {
return (





);
}

export default App;

Check out your browser window at http localhost 3000. You should now see something like this:

That’s all we need to scaffold our app. Now let’s build the input. 

Add the Input Component

Inside the RegexPhoneNumberInput, add the React Hook Form wrapper using the components and handlers that React Hook Form provides. Use the onSubmit method to mock out a function that submits the data. For now, just log it to the console.


const {
handleSubmit,
formState: { errors },
control
} = useForm();

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

The useFormReact hook gives us a handleSubmit function, which must be passed to the onSubmit handler of the <form> element, and it will be called when the user submits the form. We pass our custom onSubmit function as an argument to handleSubmit.

Delete the <div> with the text and add the form element, a <label> and the React Hook form <Controller>


const RegexPhoneNumberInput = () => {

const {
handleSubmit,
formState: { errors },
control
} = useForm();

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

return (



name="phone-input"
control={control}
render={({ field: { onChange, value } }) => (
// this is where our react-phone-number-input will go
)}
/>


);
};

Notice that we name our controller “phone-input” (this will be important when we handle errors.) We pass the control prop from the useForm hook to the <Controller>

We’ve now set up the React Hook Form logic that helps us handle the form state. The render field on the <Controller> is where the actual phone input will be rendered. Let’s add that now using react-phone-number-input.

The render field takes a function that returns a child component. The function accepts one argument, the field object, which passes to the child component an onChange handler and the field’s value.

This takes a lot of the state management out of rendering the form. React Hook Form takes care of updating the state of the form, so we don’t have to write our own initial value, use setState, or write an onChange handler.

The component we’re returning is the react-phone-number-input PhoneInput component. Let’s check out our phone number app in the browser again.

We’re now rendering a complete phone number input. We just need to add our Regex validation.

Add validation logic

React Hook Form makes validation easy. We can use the rules field of the <Controller> component to run our validation function. We could also use the isValidPhoneNumber method provided by react-phone-number-input to validate the number, however, for the sake of this tutorial, we’ll write our own customer Regex validator.

Here’s the Regex we’ll be using to validate the string.


^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$

For a thorough breakdown of how this Regex works, click here. This will match phone numbers input in the following formats:


+919367788755
8989829304
+16308520397
786-307-3615
(786) 307-3615

Create a new Regular Expression using this string. Make it global, case insensitive, and multiline.


const PHONE_REGEX =
new RegExp(/"^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$"/gmi);

Create a handleValidate method that accepts a phone number and uses the Regex.test() method to check for a positive match against the provided string.


const handleValidate = (phoneNumber) => {
return PHONE_REGEX.test(phoneNumber);
}

Now, we can just pass this custom validation function to our rules field on the <Controller>. React Hook Form will handle calling the validation function for us whenever the user updates the input.


rules={{
validate: (value) => handleValidate(value)
}}

Handle Errors

Now, we just need to show the user an error when they enter an invalid phone number. Luckily, React Hook Form makes this super easy as well. React Hook Form will catch any errors that arise from running the validation function we gave it.

React Hook Form gives us access to an errors object in the useForm hook. We can use that to track our errors and render a message if one exists.


const {
handleSubmit,
formState: { errors },
control
} = useForm();

const handleValidate = (phoneNumber) => {
if (PHONE_REGEX.test(phoneNumber)) {
errors["phoneNumber"] = null;
} else {
errors["phoneNumber"] = "Invalid phone number. Please try again."
}
return PHONE_REGEX.test(phoneNumber);
}
{!!errors.phoneNumber &&

{errors.phoneNumber}

}

Put It All Together

Here’s the full code for our phone number input component.


import React from "react";
import { useForm, Controller } from "react-hook-form";
import PhoneInput, { isValidPhoneNumber } from "react-phone-number-input";
import "react-phone-number-input/style.css";

const PHONE_REGEX = new RegExp(/"^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$"/gmi);

const RegexPhoneNumberInput = () => {

const {
handleSubmit,
formState: { errors },
control
} = useForm();
const onSubmit = (data) => {
console.log({data});
};

const handleValidate = (phoneNumber) => {
if (PHONE_REGEX.test(phoneNumber)) {
errors["phoneNumber"] = null;
} else {
errors["phoneNumber"] = "Invalid phone number. Please try again."
}
return PHONE_REGEX.test(phoneNumber);
}

return (



name="phone-input"
control={control}
rules={{
validate: (value) => handleValidate(value)
}}
render={({ field: { onChange, value } }) => (
value={value}
onChange={onChange}
defaultCountry="US"
id="phone-input"
/>
)}
/>
{!!errors.phoneNumber &&

{errors.phoneNumber}

}


);
};
export default RegexPhoneNumberInput;

Additional Idea: Validation Through a Dedicated Library

A much better idea is to use a validation library or a dedicated phone number validation API. That way, the nitty-gritty of parsing, cleaning, and comparing a string of numbers is put on the library or API. All you have to do is collect the user’s number and pass it off to the validator. 

A great API for this is AbstractAPI’s free phone number validator. You can send any phone number to the API’s REST endpoint and get back a JSON object with a validation boolean and additional information about the number.

The object that AbstractAPI returns look 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."
}

Let’s rewrite our handleValidate method to use the AbstractAPI phone validation endpoint instead of the Regex.

Acquire an API key

You’ll need an API key to use the AbstractAPI endpoint. Navigate to the API documentation page. You’ll see an example of the API’s JSON response object to the right, and a “Get Started” button to the left.

Click “Get Started.” You’ll be asked to create an account using your email and a password. If you already have an AbstractAPI account, you’ll be asked to log in. 

Every AbstractAPI API needs a unique key, so if you have an existing API key from a different API, you’ll be given a new one for this API. You’ll land on the API homepage.

Rewrite the Validation Using the API

We’ll first write a function that uses fetch to send a GET request to the API endpoint, with our API key and the phone number for validation.


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

async function sendValidationRequest(phoneNumber) {
try {
const response = await (await fetch(apiURL + "&phone=" + phoneNumber)).json();
return response.data.valid
} catch (error) {
throw error
}
}

We could call out sendValidationRequest method inside our handleValidate function instead of using the Regex validator. However, React Hook will call this validation function on every keystroke, meaning we’d be sending an AJAX request to the endpoint on every keystroke, and we’d quickly hit a 429 “Too many requests” error.

Instead, we’ll move the validation logic to the onSubmit function.


const onSubmit = async (data) => {
const isValid = await sendValidationRequest(data["phone-input"]);
if (isValid) {
errors["phoneNumber"] = null;
console.log({data});
} else {
errors["phoneNumber"] = "Invalid phone number. Please try again."
}
};

We had to turn our onSubmit into an async function since we’re now sending a network request. The data will only be submitted if the API tells us the phone number is valid. Otherwise, we’ll display an error to our users.

We could remove the Regex validation from the form, or leave it in. It doesn’t hurt to have two levels of validation in a user form. 

Elizabeth (Lizzie) Shipton

Lizzie Shipton is an adept Full Stack Developer, skilled in JavaScript, React, Node.js, and GraphQL, with a talent for creating scalable, seamless web applications. Her expertise spans both frontend and backend development, ensuring innovative and efficient solutions.

Get your free
Phone Validation
key now
See why the best developers build on Abstract
get started for free

Related Articles

Get your free
Phone Validation
key now
4.8 from 1,863 votes
See why the best developers build on Abstract
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
No credit card required