Guides
Last updated
June 5, 2024

Phone Number Validation in React Native

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

If you're building a React Native application, phone authentication is easy. React Native is a Javascript framework that allows you to build apps for iOS, Android, Windows, and other platforms using the same React JS code you already know and love.

The best part is you can use many of the same libraries that you would use to build a React app, including phone authentication libraries.

This article will explore setting up a basic phone input with phone authentication in React Native. We'll build a React app running on iOS, using Native Components and react-native-phone-input. For validation, we’ll look at two methods: the provided isValidNumber method from the React Native package, and a dedicated phone validation API from AbstractAPI.

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

Prerequisites

This article will not teach you how to use React JS or React Native. If you’re not already familiar with React JS, we recommend checking out the ReactJS docs to get started.

If you're unfamiliar with React Native, we recommend using Expo to get started with React Native. Expo is to React Native what Create React App is to React. It helps you get a React Native dev environment up and running without writing a lot of boilerplate or installing a lot of tools.

You will need to install the Expo Go app on an iOS device. This tutorial won’t dive into specifics of how to get started with Expo or Expo Go—for more detail on that, check out the Expo docs.

Get Started

Use the Expo command-line interface to spin up your phone verification application. This is kind of like running npx create-react-app for a React JS app. If you are not using expo, you would run react native init to run the React Native Application instead.


$ expo init react-native-phone-number-validation
$ cd react-native-phone-number-validation

We’ll be working with Native Components, which are part of the React Native Core library. We’ll also be using an NPM package to build the actual phone input, so let’s install that too.


$ npm install –-save react-native-phone-input

To check that things are working, let’s start up the app.


$ expo start

This command tells Expo to start the Metro bundler, which compiles and bundles the code and serves it to the Expo Go app. Scan the QR code in your console using the phone’s camera to connect to the Metro bundler. This will open up the app on your phone.


That’s it! Our simple React Native app is now up and running.

Build a Phone Number Input With Native Components

Create the PhoneNumberInput Component

Create a new file next to App.js called PhoneNumberInput.js. We’ll put all the form and validation logic in this file and render the component here. Inside the file, create a PhoneNumberInput component.

 
import React, { useState, useRef } from "react";
import { SafeAreaView, StyleSheet, Text, TouchableHighlight } from "react-native";
import PhoneInput from "react-native-phone-input";
 
const PhoneNumberInput = () => {
  const [phoneNumber, setPhoneNumber] = useState("");
   const phoneInput = useRef<PhoneInput>(null);
 
 
  const handleSubmit = () => {
   // we’ll write this next
  }
  return (
    <SafeAreaView>
          <PhoneInput
               style={styles.phoneInput}
               initialValue={phoneNumber}
               initialCountry="us"
               onChangeText={(text) => {
                   setPhoneNumber(text);
               }}
               withShadow
               autoFocus
           />
      <TouchableHighlight onPress={handleSubmit}>
         <Text>Submit</Text>
      </TouchableHighlight>
   </SafeAreaView>
  )
}
const styles = StyleSheet.create({
   phoneInput: {
       borderWidth: 1,
       borderRadius: 25,
       width: 250,
       height: 50,
       padding: 5,
   },
  button: {
      borderWidth: 1,
      borderColor: 'green',
      borderRadius: 15,
      marginTop: 25,
      padding: 10,
      alignItems: 'center'
  },
});
export default PhoneNumberInput;

We’ve used the useState hook to set the initial phoneNumber to an empty string and passed that to the PhoneNumberInput component as its defaultValue prop. The onChangeText handler will update the phone number in state to the inputted value.

Next, we scaffolded out a handleSubmit function that will be called when the user taps the “Submit” button. That is where we will put our validation logic too.

You’ll notice that the PhoneNumberInput uses a ref. This is used to do validation through a isValidNumber method that the package provides. If you’re not sure how to use refs, check out this tutorial.

We’ve used the SafeAreaView component to make sure the form renders in the correct place on the mobile screen, and we’ve added some basic styling using the StyleSheet component.

Next, we’ll write the handleSubmit function, which will validate the email input before submitting it.

Add Validation Logic

Our handleSubmit function will pull the phoneNumber value out of state, validate it, and then—as long as validation is successful—submit the email to our server (for now, we’re actually just logging the value to the console.)

We’ll look at two methods of validation: using the isValidNumber method provided by the NPM phone input package, and sending the number to AbstractAPI’s Free Phone Number Validation endpoint.

Use the isValidNumber Method

The NPM package we get the phone input component from comes with a handy validation method to check a number’s length and formatting. To use it, grab the phoneInput ref we created earlier, access the ref’s current value, and call the function.


  const handleSubmit = (phoneNumber) => {
       const isValid = phoneInput.current?.isValidNumber(phoneNumber);
       if (isValid) {
           console.log("SUBMITTED! ", phoneNumber)
       } else {
           console.log("INVALID NUMBER.")
       }
   }

Use AbstractAPI’s Phone Validation Endpoint

If you want more information than this validation method provides, or if you’d rather not use a React ref hook (they can be notoriously tricky to work with) you can use the AbstractAPI Phone Validation endpoint instead.

Acquire an API Key

Go to the Phone Validation API page and click the blue “Get Started” button.


You’ll need to either sign up or log in. Once you’ve done that, you’ll be taken to the API’s homepage, where you’ll see options for documentation, pricing, and support, and you’ll see your API key. 

Each Abstract API has a unique key, so even if you’ve used another Abstract API before, this key will be unique. Don’t attempt to use a different AbstractAPI key.

Send a Request to the API

React Native uses the Fetch API to send and receive HTTP requests. 

Let’s write a function called sendPhoneNumberValidationRequest to send the request to the API endpoint using Fetch.


const apiKey = 'YOUR_API_KEY';
const apiURL = 'https://phonevalidation.abstractapi.com/v1/?api_key=' + apiKey;
...
   const sendPhoneNumberValidationRequest = async (phoneNumber) => {
       try {
           const response = await fetch.get(apiURL + '&phone=' + phoneNumber);
           console.log(response.json())
       } catch (error) {
           throw error;
       }
   }

Don’t forget to call .json() on the response to parse it correctly. The data inside the response should look something 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."
}


For now, the only part we’re interested in is the valid boolean value. We’ll return this value from our sendPhoneNumberValidationRequest function. 

           const response = await fetch.get(apiURL + '&phone=' + phoneNumber);
           const data = response.json();
           return data.valid;

Use the Validation Response in the handleSubmit Function

Now that we have our response from the API, let’s put it into our handleSubmit function. Remove the previous validation check that we did with the isValidNumber method. You can also remove any code referring to the useRef hook and the ref itself.

   const handleSubmit = async (phoneNumber) => {
       const isValid = await sendPhoneNumberValidationRequest(phoneNumber);
       if (isValid) {
           console.log("SUBMITTED! ", phoneNumber);
       } else {
           console.log("INVALID NUMBER.");
       }
       return isValid;
   }

import React, { useState, useRef } from "react"; // remove useRef
...
   const phoneInput = useRef<PhoneInput>(null); //remove this
...
           ref={phoneInput} // remove this

Note that we turned our handleSubmit function into an async function because we are now making an API call to validate the number.

Render the Form in App.js

Remove everything between the outermost <div> elements inside App.js. Import your new phone number input and render that React component instead.

import { StatusBar } from 'expo-status-bar';
import { StyleSheet, View } from 'react-native';
import PhoneNumberInput from './PhoneNumber;
 
export default function App() {
 return (
   <View style={styles.container}>
     <PhoneNumberInput/>
     <StatusBar style="auto" />
   </View>
 );
}
 
const styles = StyleSheet.create({
 container: {
   flex: 1,
   backgroundColor: '#fff',
   alignItems: 'center',
   justifyContent: 'center',
 },
});


Visit the Expo Go app again. Your new input should be rendered!


Error Handling

If phone number validation fails, or if something else goes wrong while the request is being sent to the API, we need to let the user know. Let’s render an error message to tell the user what went wrong.

   const [errorMessage, setErrorMessage] = useState("");
...
   const handleSubmit = async (phoneNumber) => {
       try {
           const isValid = await sendPhoneNumberValidationRequest(phoneNumber);
           if (isValid) {
               setErrorMessage("");
               console.log("SUBMITTED! ", phoneNumber);
           } else {
               setErrorMessage("INVALID PHONE NUMBER.PLEASE CHECK YOUR INPUT AND TRY AGAIN.");
               console.log("INVALID NUMBER.");
           }
           return isValid;
       } catch (error) {
           setErrorMessage("COULD NOT VALIDATE PHONE NUMBER.PLEASE TRY AGAIN LATER.");
       }
   }

We created an errorMessage value in state, and initialized it to and empty string. Then, if the response that comes back from the API is valid: false, we update the state with an error message to let the user know the phone number is invalid.

We also added some better error handling around the async/await code to  handle network failures and other errors. We wrapped the HTTP request in a try/catch block so that if anything goes wrong, we catch the error and display an error message to the user.

The last thing we need to do is render the errorMessage so the user can see it. We’ll use the React Native <Text/> component to do this.

...    
       <TouchableHighlight onPress={handleSubmit} style={styles.button}>
         <Text>Submit</Text>
       </TouchableHighlight>
   <Text style={styles.error}>{errorMessage}</Text> // added this
...
const styles = StyleSheet.create({
   button: {
       borderWidth: 1,
       borderColor: 'green',
       borderRadius: 15,
       marginTop: 25,
       padding: 10,
       alignItems: 'center'
   },
   error: {
       color: 'red' // added this
   }
});

 

Put it All Together

Let’s take a look at the complete code for our PhoneNumberInput React component, including error handling.

import React, { useState } from "react";
import { SafeAreaView, TouchableHighlight, Text, StyleSheet } from "react-native";
import PhoneInput from "react-native-phone-input";
 
const apiKey = 'YOUR_API_KEY';
const apiURL = 'https://phonevalidation.abstractapi.com/v1/?api_key=' + apiKey
const PhoneNumberInput = () => {
   const [phoneNumber, setPhoneNumber] = useState("");
   const [errorMessage, setErrorMessage] = useState("");
 
 
   const handleSubmit = async (phoneNumber) => {
       try {
           const isValid = await sendPhoneNumberValidationRequest(phoneNumber);
           if (isValid) {
               setErrorMessage("");
               console.log("SUBMITTED! ", phoneNumber);
           } else {
               setErrorMessage("Invalid phone number. Please try again.");
               console.log("INVALID NUMBER.");
           }
           return isValid;
       } catch (error) {
           setErrorMessage("SOMETHING WENT WRONG.PLEASE TRY AGAIN LATER.");
       }
   }
  
   const sendPhoneNumberValidationRequest = async (phoneNumber) => {
       try {
           const response = await fetch.get(apiURL + '&phone=' + phoneNumber);
           const data = response.json();
           return data.is_valid_format.value;
       } catch (error) {
           throw error;
       }
   }
 
  return (
    <SafeAreaView>
          <PhoneInput
               style={styles.phoneInput}
               initialValue={phoneNumber}
               initialCountry="us"
               onChangeText={(text) => {
                   setPhoneNumber(text);
               }}
           />
       <TouchableHighlight onPress={handleSubmit} style={styles.button}>
         <Text>Submit</Text>
       </TouchableHighlight>
       <Text style={styles.error}>{errorMessage}</Text>
   </SafeAreaView>
  )
}
const styles = StyleSheet.create({
   phoneInput: {
       borderWidth: 1,
       borderRadius: 25,
       width: 250,
       height: 50,
       padding: 5,
   },
   button: {
       borderWidth: 1,
       borderColor: 'green',
       borderRadius: 15,
       marginTop: 25,
       padding: 10,
       alignItems: 'center'
   },
   error: {
       color: 'red'
   }
});
 
export default PhoneNumberInput;


Type an invalid phone number into the input and click “Submit.” The sendPhoneNumberVerification function sends a request to the API, which will come back false. Our error handling logic then sets the errorMessage value and renders an error message.

That was a basic overview of setting up a simple phone number input with validation in React Native. There’s a lot more that can be done to improve this. For example, we can customize the style of the input and add a loading spinner while the handleSubmit function is running to let the user know the app is busy.

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