Détail du package

react-native-international-phone-number

AstrOOnauta60.1kISC0.10.0

International mobile phone input component with mask for React Native

mobile, ios, android, react-native

readme


React Native International Phone Number Input Lib preview


React Native International Phone Number Input



Features

  • 🌎 Phone Input Mask – Auto-formatting per selected country
  • Validation - Check phone number;
  • 📱 Cross-Platform – Works seamlessly on iOS, Android and Web;
  • 🧩 Flexible Integration – Supports both React Native CLI & Expo;
  • 👨‍💻 Component Versatility - Works with functional & class components;
  • 🎨 Modern UI - Custom component with sleek design;
  • 🈶 internationalization - Supports 32 languages;
  • 🧪 Test Ready – Smooth testing integration;
  • Accessibility – Accessibility standards to screen readers.


Try it out


List of Contents


Old Versions


Installation

$ npm i --save react-native-international-phone-number

OR

$ yarn add react-native-international-phone-number

Additional config to WEB

  • Using React Native CLI:

Create a react-native.config.js file at the root of your react-native project with:

module.exports = {
  project: {
    ios: {},
    android: {},
  },
  assets: [
    './node_modules/react-native-country-select/lib/assets/fonts',
  ],
};

Then link the font to your native projects with:

npx react-native-asset
  • Using Expo:

  • Install expo-fonts: npx expo install expo-font;

  • Initialize the expo-font:
  import { useFonts } from 'expo-font';

  ...

  useFonts({
    'TwemojiMozilla': require('./node_modules/react-native-country-select/lib/assets/fonts/TwemojiMozilla.woff2'),
  });

  ...

Observation: you need to recompile your project after adding new fonts.


Basic Usage

  • Class Component:

import React from 'react';
import { View, Text } from 'react-native';
import PhoneInput, { isValidPhoneNumber } from 'react-native-international-phone-number';

export class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      selectedCountry: null,
      inputValue: ''
    }
  }

  function handleSelectedCountry(country) {
    this.setState({
      selectedCountry: country
    })
  }

  function handleInputValue(phoneNumber) {
    this.setState({
      inputValue: phoneNumber
    })
  }

  render(){
    return (
      <View style={{ width: '100%', flex: 1, padding: 24 }}>
        <PhoneInput
          value={this.state.inputValue}
          onChangePhoneNumber={this.handleInputValue}
          selectedCountry={this.state.selectedCountry}
          onChangeSelectedCountry={this.handleSelectedCountry}
        />
        <View style={{ marginTop: 10 }}>
          <Text>
            Country:{' '}
            {`${this.state.selectedCountry?.translations?.eng?.common} (${this.state.selectedCountry?.cca2})`}
          </Text>
          <Text>
            Phone Number: {`${this.state.selectedCountry?.idd?.root} ${this.state.inputValue}`}
          </Text>
          <Text>
            isValid:{' '}
            {isValidPhoneNumber(this.state.inputValue, this.state.selectedCountry)
              ? 'true'
              : 'false'}
          </Text>
        </View>
      </View>
    );
  }
}
  • Function Component:

import React, {useState} from 'react';
import {View, Text} from 'react-native';
import PhoneInput, {
  isValidPhoneNumber,
} from 'react-native-international-phone-number';

export default function App() {
  const [selectedCountry, setSelectedCountry] = useState(null);
  const [inputValue, setInputValue] = useState('');

  function handleInputValue(phoneNumber) {
    setInputValue(phoneNumber);
  }

  function handleSelectedCountry(country) {
    setSelectedCountry(country);
  }

  return (
    <View style={{width: '100%', flex: 1, padding: 24}}>
      <PhoneInput
        value={inputValue}
        onChangePhoneNumber={handleInputValue}
        selectedCountry={selectedCountry}
        onChangeSelectedCountry={handleSelectedCountry}
      />
      <View style={{marginTop: 10}}>
        <Text>
          Country:{' '}
          {`${selectedCountry?.translations?.eng?.common} (${selectedCountry?.cca2})`}
        </Text>
        <Text>
          Phone Number: {`${selectedCountry?.idd?.root} ${inputValue}`}
        </Text>
        <Text>
          isValid:{' '}
          {isValidPhoneNumber(inputValue, selectedCountry) ? 'true' : 'false'}
        </Text>
      </View>
    </View>
  );
}
  • Typescript

import React, {useState} from 'react';
import {View, Text} from 'react-native';
import PhoneInput, {
  ICountry,
  isValidPhoneNumber,
} from 'react-native-international-phone-number';

export default function App() {
  const [selectedCountry, setSelectedCountry] = useState<null | ICountry>(null);
  const [inputValue, setInputValue] = useState<string>('');

  function handleInputValue(phoneNumber: string) {
    setInputValue(phoneNumber);
  }

  function handleSelectedCountry(country: ICountry) {
    setSelectedCountry(country);
  }

  return (
    <View style={{width: '100%', flex: 1, padding: 24}}>
      <PhoneInput
        value={inputValue}
        onChangePhoneNumber={handleInputValue}
        selectedCountry={selectedCountry}
        onChangeSelectedCountry={handleSelectedCountry}
      />
      <View style={{marginTop: 10}}>
        <Text>
          Country:{' '}
          {`${selectedCountry?.translations?.eng?.common} (${selectedCountry?.cca2})`}
        </Text>
        <Text>
          Phone Number: {`${selectedCountry?.idd?.root} ${inputValue}`}
        </Text>
        <Text>
          isValid:{' '}
          {isValidPhoneNumber(inputValue, selectedCountry) ? 'true' : 'false'}
        </Text>
      </View>
    </View>
  );
}


Intermediate Usage

  • Typescript + useRef

import React, {useRef} from 'react';
import {View, Text} from 'react-native';
import PhoneInput, {
  ICountry,
  IPhoneInputRef,
} from 'react-native-international-phone-number';

export default function App() {
  const phoneInputRef = useRef<IPhoneInputRef>(null);

  function onSubmitRef() {
    Alert.alert(
      'Intermediate Result',
      `Country: ${inputRef.current?.selectedCountry?.translations?.eng?.common} \nPhone Number: ${inputRef.current?.fullPhoneNumber} \nisValid: ${inputRef.current?.isValid}`,
    );
  }

  return (
    <View style={{width: '100%', flex: 1, padding: 24}}>
      <PhoneInput ref={phoneInputRef} />
      <TouchableOpacity
        style={{
          width: '100%',
          paddingVertical: 12,
          backgroundColor: '#2196F3',
          borderRadius: 4,
          marginTop: 10,
        }}
        onPress={onSubmit}>
        <Text
          style={{
            color: '#F3F3F3',
            textAlign: 'center',
            fontSize: 16,
            fontWeight: 'bold',
          }}>
          Submit
        </Text>
      </TouchableOpacity>
    </View>
  );
}

Observation: Don't use the useRef hook combined with the useState hook to manage the phoneNumber and selectedCountry values. Instead, choose to use just one of them (useRef or useState).


Advanced Usage

  • React-Hook-Form + Typescript + Default Phone Number Value

import React, {useState, useEffect} from 'react';
import {View, Text, TouchableOpacity, Alert} from 'react-native';
import PhoneInput, {
  ICountry,
  isValidPhoneNumber,
} from 'react-native-international-phone-number';
import {Controller, FieldValues} from 'react-hook-form';

interface FormProps extends FieldValues {
  phoneNumber: string;
}

export default function App() {
  const [selectedCountry, setSelectedCountry] = useState<undefined | ICountry>(
    undefined,
  );

  function handleSelectedCountry(country: ICountry) {
    setSelectedCountry(country);
  }

  function onSubmit(form: FormProps) {
    const phoneNumber = `${selectedCountry?.idd?.root} ${form.phoneNumber}`;
    const isValid = isValidPhoneNumber(
      form.phoneNumber,
      selectedCountry as ICountry,
    );

    Alert.alert(
      'Advanced Result',
      `Country: ${selectedCountry?.translations?.eng?.common} \nPhone Number: ${phoneNumber} \nisValid: ${isValid}`,
    );
  }

  return (
    <View style={{width: '100%', flex: 1, padding: 24}}>
      <Controller
        name="phoneNumber"
        control={control}
        render={({field: {onChange, value}}) => (
          <PhoneInput
            defaultValue="+12505550199"
            value={value}
            onChangePhoneNumber={onChange}
            selectedCountry={selectedCountry}
            onChangeSelectedCountry={handleSelectedCountry}
          />
        )}
      />
      <TouchableOpacity
        style={{
          width: '100%',
          paddingVertical: 12,
          backgroundColor: '#2196F3',
          borderRadius: 4,
        }}
        onPress={handleSubmit(onSubmit)}>
        <Text
          style={{
            color: '#F3F3F3',
            textAlign: 'center',
            fontSize: 16,
            fontWeight: 'bold',
          }}>
          Submit
        </Text>
      </TouchableOpacity>
    </View>
  );
}

Observations:

  1. You need to use a default value with the following format: +(country callling code)(area code)(number phone)
  2. The lib has the mechanism to set the flag and mask of the supplied defaultValue. However, if the supplied defaultValue does not match any international standard, the input mask of the defaultValue will be set to "BR" (please make sure that the default value is in the format mentioned above).


Customizing lib

PhoneInput Styles (phoneInputStyles)

Property Type Description
container ViewStyle Main input container
flagContainer ViewStyle Flag and dropdown container
flag TextStyle Flag emoji styling
caret TextStyle Dropdown arrow
divider ViewStyle Separator line
callingCode TextStyle Country calling code
input TextStyle Phone number input

Modal Styles (modalStyles)

Property Type Description
backdrop ViewStyle Modal background overlay
container ViewStyle Modal main container
content ViewStyle Modal content area
searchContainer ViewStyle Search input wrapper
searchInput TextStyle Search input field
list ViewStyle Countries list container
countryItem ViewStyle Individual country row
flag TextStyle Country flag in list
countryInfo ViewStyle Country details container
callingCode TextStyle Calling code in list
countryName TextStyle Country name in list
sectionTitle TextStyle Section headers
closeButton ViewStyle Close button container
closeButtonText TextStyle Close button text
countryNotFoundContainer ViewStyle No results container
countryNotFoundMessage TextStyle No results message


Component Props (PhoneInputProps)

Prop Type Description
theme ITheme Theme configuration for the component
language ILanguage Language for country names and UI
defaultValue string Default phone number value (format: +(country code)(area code)(number))
value string Controlled phone number value
onChangePhoneNumber (phoneNumber: string) => void Callback when phone number changes
defaultCountry ICountryCca2 Default selected country (ISO 3166-1 alpha-2)
selectedCountry ICountry Currently selected country object
onChangeSelectedCountry (country: ICountry) => void Callback when country selection changes
placeholder string Placeholder text for phone input
phoneInputPlaceholderTextColor string Color of placeholder text
phoneInputSelectionColor string Color of text selection
phoneInputStyles IPhoneInputStyles Custom styles for phone input component
modalStyles ICountrySelectStyles Custom styles for country selection modal
disabled boolean Disable the entire phone input
modalDisabled boolean Disable only the country selection modal
visibleCountries ICountryCca2[] Array of country codes to show in modal
hiddenCountries ICountryCca2[] Array of country codes to hide from modal
popularCountries ICountryCca2[] Array of country codes to show in popular section
customCaret () => ReactNode Custom dropdown arrow component
rtl boolean Enable right-to-left layout
isFullScreen boolean Show modal in full screen mode
modalType `'bottomSheet' \ 'popup'` Type of modal presentation
modalSearchInputPlaceholderTextColor string Color of modal search placeholder text
modalSearchInputPlaceholder string Placeholder text for modal search input
modalSearchInputSelectionColor string Color of modal search text selection
modalPopularCountriesTitle string Title for popular countries section
modalAllCountriesTitle string Title for all countries section
modalSectionTitleComponent () => ReactNode Custom section title component
modalCountryItemComponent () => ReactNode Custom country item component
modalCloseButtonComponent () => ReactNode Custom close button component
modalSectionTitleDisabled boolean Disable section titles in modal
modalNotFoundCountryMessage string Message when no countries found
disabledModalBackdropPress boolean Disable modal close on backdrop press
removedModalBackdrop boolean Remove modal backdrop entirely
onModalBackdropPress () => void Callback when modal backdrop is pressed
onModalRequestClose () => void Callback when modal close is requested
showModalSearchInput boolean Show search input in modal
showModalCloseButton boolean Show close button in modal
showModalScrollIndicator boolean Show scroll indicator in modal
ref Ref<IPhoneInputRef> Ref to access component methods


Functions

Function Parameters Return Type Description
getAllCountries () ICountry[] Returns an array of all available countries
getCountriesByCallingCode (callingCode: string) `ICountry[] \ undefined` Returns countries that match the given calling code
getCountryByCca2 (cca2: string) `ICountry \ undefined` Returns a country by its ISO 3166-1 alpha-2 code
getCountriesByName (name: string, language: ILanguage) `ICountry[] \ undefined` Returns countries that match the given name in the specified language
getCountryByPhoneNumber (phoneNumber: string) `ICountry \ undefined` Returns the country that matches the given phone number
isValidPhoneNumber (phoneNumber: string, country: ICountry) boolean Validates if a phone number is valid for the given country


Supported languages

The language prop supports the following values:

Code Language
ara Arabic
bel Belarusian
bre Breton
bul Bulgarian
ces Czech
deu German
ell Greek
eng English
est Estonian
fin Finnish
fra French
heb Hebrew
hrv Croatian
hun Hungarian
ita Italian
jpn Japanese
kor Korean
nld Dutch
per Persian
pol Polish
por Portuguese
ron Romanian
rus Russian
slk Slovak
spa Spanish
srp Serbian
swe Swedish
tur Turkish
ukr Ukrainian
urd Urdu
zho Chinese
zho-Hans Simplified Chinese
zho-Hant Traditional Chinese


Testing

When utilizing this package, you may need to target the PhoneInput component in your automated tests. To facilitate this, we provide a testID props for the PhoneInput component. The testID can be integrated with popular testing libraries such as @testing-library/react-native or Maestro. This enables you to efficiently locate and interact with PhoneInput elements within your tests, ensuring a robust and reliable testing experience.

const phoneInput = getByTestId('countryPickerPhoneInput');
const flagContainerButton = getByTestId('countryPickerFlagContainerButton');
const countrySelect = getByTestId('countrySelectSearchInput');
const countrySelectBackdrop = getByTestId('countrySelectBackdrop');
const countrySelectList = getByTestId('countrySelectList');
const countrySelectSearchInput = getByTestId('countrySelectSearchInput');
const countrySelectItem = getByTestId('countrySelectItem');
const countrySelectCloseButton = getByTestId('countrySelectCloseButton');


Accessibility

Ensure your app is inclusive and usable by everyone by leveraging built-in React Native accessibility features. The accessibility props are covered by this package.


Contributing

  • Fork or clone this repository
  $ git clone https://github.com/AstrOOnauta/react-native-international-phone-number.git
  • Repair, Update and Enjoy 🛠️🚧⚙️

  • Create a new PR to this repository


License

ISC



Thanks for stopping by! 😁