Hey guys, I am back with another simple tutorial, in this article, we are going to make a phone number input in react native.

Phone number input is just like a normal input field but it contains country code as prefix, there will also be a country code picker, so that we can pick the relevant country code from it. Below are the previews.

There are few react native packages available in the market, but you can also make one by yourself. Believe me, it is not that difficult.

The main part of this phone number input is having list of country names along with their country codes and emojis. You don’t have to worry about it. You can just grab the countryCodes.json from my github here.

Once you get the file from github, we are good to go.

I am making this phone number input using the overlay, input and some components from popular react native library react-native-elements.

Let’s start coding… create a file named FullPhoneNumber.js in your existing or new react native project. And also move your downloaded countryCodes.json file into your project.

The idea is to create component named FullPhoneNumber which is a phone number input field, so that we can use it like below wherever needed.

<FullPhoneNumber
  onChangeText={fullPhoneNumber => {
    console.log(fullPhoneNumber)
  }}
  errorMessage=''
/>

Now open FullPhoneNumber.js file and import necessary modules like.

import React, { Component } from 'react'

import { View, StyleSheet, FlatList } from 'react-native'

import PropTypes from 'prop-types'

import {
  Input,
  Button,
  Overlay,
  ListItem,
  SearchBar,
  Icon
} from 'react-native-elements'

If you look at the above imports, we are using Button to pick country code, and Input for entering phone number. FlatList and ListItem are used for displaying country wise details in picker. Overlay to display FlatList. And SearchBar to search country from the FlatList.

We are also using Icon as close button on Overlay to close the overlay.

Now lets create a class called FullPhoneNumber which extends Component from react-native.

Create constructor and add defaultProps values and propTypes like below.

export default class FullPhoneNumber extends Component {
  static propTypes = {
    onChangeText: PropTypes.func,

    errorMessage: PropTypes.string,

    placeholder: PropTypes.string
  }

  static defaultProps = {
    errorMessage: '',

    placeholder: 'Phone number'
  }

  constructor (props) {
    super(props)

    this.state = {
      isVisible: false,

      search: '',

      emoji: '??',

      code: '+91'
    }
  }
}

In the above code, we have added some default state values like emoji, code, search and isVisible.

Now let’s add render method to FullPhoneNumber component.

export default class FullPhoneNumber extends Component {
  static propTypes = {
    onChangeText: PropTypes.func,

    errorMessage: PropTypes.string,

    placeholder: PropTypes.string
  }

  static defaultProps = {
    errorMessage: '',

    placeholder: 'Phone number'
  }

  constructor (props) {
    super(props)

    this.state = {
      isVisible: false,

      search: '',

      emoji: '??',

      code: '+91'
    }
  }
  
  ...
 
  render () {
    const { search } = this.state

    return (
      <View style={styles.container}>
        <View style={styles.buttonViewStyle}>
          <Button
            buttonStyle={styles.buttonStyle}
            titleStyle={styles.buttonTitleStyle}
            title={this.state.emoji + ' ' + this.state.code}
            onPress={() => this.selectCountry()}
            containerStyle={styles.buttonContainerStyle}
          />
        </View>

        <View style={styles.inputViewStyle}>
          <Input
            keyboardType='number-pad'
            placeholder={this.props.placeholder}
            inputStyle={styles.inputStyle}
            containerStyle={styles.inputContainerStyle}
            onChangeText={text => this.inputTextChange(text)}
            errorMessage={this.props.errorMessage}
          />
        </View>

        <Overlay
          fullScreen
          isVisible={this.state.isVisible}
          onBackdropPress={this.closeOverlay}
        >
          <View>
            <Icon
              name='close'
              containerStyle={styles.iconContainerStyle}
              onPress={this.closeOverlay}
            />

            <SearchBar
              placeholder='Search by country or code '
              onChangeText={this.updateSearch}
              value={search}
              containerStyle={styles.searchBarContainerStyle}
              inputContainerStyle={styles.searchBarInputContainerStyle}
              inputStyle={styles.searchBarInputStyle}
            />

            <FlatList
              keyboardShouldPersistTaps='handled'
              keyExtractor={this.keyExtractor}
              data={this.list}
              renderItem={this.renderItem}
            />
          </View>
        </Overlay>
      </View>
    )
  }
}

If you keenly observe the above code, you will find Button and Input are placed next to each other.

Button acts as display to showcase country code and also it shows overlay whenever clicked to pick county code.

By default, overlay will not be shown as the isVisible is false. Observe overlay it contains Icon to close the overlay on pressed. Contains SearchBar and FlatList to search and display country codes respectively.

We also need to adjust the above components with styles, let’s add them.

export default class FullPhoneNumber extends Component {
  static propTypes = {
    onChangeText: PropTypes.func,

    errorMessage: PropTypes.string,

    placeholder: PropTypes.string
  }

  static defaultProps = {
    errorMessage: '',

    placeholder: 'Phone number'
  }

  constructor (props) {
    super(props)

    this.state = {
      isVisible: false,

      search: '',

      emoji: '??',

      code: '+91'
    }
  }

  ...

  render () {
    const { search } = this.state

    return (
      <View style={styles.container}>
        <View style={styles.buttonViewStyle}>
          <Button
            buttonStyle={styles.buttonStyle}
            titleStyle={styles.buttonTitleStyle}
            title={this.state.emoji + ' ' + this.state.code}
            onPress={() => this.selectCountry()}
            containerStyle={styles.buttonContainerStyle}
          />
        </View>

        <View style={styles.inputViewStyle}>
          <Input
            keyboardType='number-pad'
            placeholder={this.props.placeholder}
            inputStyle={styles.inputStyle}
            containerStyle={styles.inputContainerStyle}
            onChangeText={text => this.inputTextChange(text)}
            errorMessage={this.props.errorMessage}
          />
        </View>

        <Overlay
          fullScreen
          isVisible={this.state.isVisible}
          onBackdropPress={this.closeOverlay}
        >
          <View>
            <Icon
              name='close'
              containerStyle={styles.iconContainerStyle}
              onPress={this.closeOverlay}
            />

            <SearchBar
              placeholder='Search by country or code '
              onChangeText={this.updateSearch}
              value={search}
              containerStyle={styles.searchBarContainerStyle}
              inputContainerStyle={styles.searchBarInputContainerStyle}
              inputStyle={styles.searchBarInputStyle}
            />

            <FlatList
              keyboardShouldPersistTaps='handled'
              keyExtractor={this.keyExtractor}
              data={this.list}
              renderItem={this.renderItem}
            />
          </View>
        </Overlay>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  buttonStyle: {
    backgroundColor: 'white',

    height: 50
  },

  buttonTitleStyle: {
    color: 'black',

    fontSize: 20,

    justifyContent: 'center'
  },

  buttonViewStyle: { flex: 0.3 },

  container: {
    alignItems: 'center',

    backgroundColor: 'white',

    flexDirection: 'row',

    margin: 10,

    marginRight: 20
  },

  iconContainerStyle: { height: 50, width: 50 },

  inputStyle: {
    fontSize: 20
  },

  inputViewStyle: {
    alignItems: 'flex-start',

    flex: 0.7,

    justifyContent: 'center',

    marginTop: 20
  },

  searchBarContainerStyle: {
    backgroundColor: 'white',

    borderBottomColor: 'white',

    borderTopColor: 'white'
  },

  searchBarInputContainerStyle: {
    backgroundColor: 'white'
  },

  searchBarInputStyle: {
    color: 'black'
  }
})

Lastly we need to add some methods for functioning of SearchBar, Overlay Input and Button, let’s do it..

import React, { Component } from 'react'

import { View, StyleSheet, FlatList } from 'react-native'

import PropTypes from 'prop-types'

import {
  Input,
  Button,
  Overlay,
  ListItem,
  SearchBar,
  Icon
} from 'react-native-elements'

export default class FullPhoneNumber extends Component {
  static propTypes = {
    onChangeText: PropTypes.func,

    errorMessage: PropTypes.string,

    placeholder: PropTypes.string
  }

  static defaultProps = {
    errorMessage: '',

    placeholder: 'Phone number'
  }

  constructor (props) {
    super(props)

    this.state = {
      isVisible: false,

      search: '',

      emoji: '??',

      code: '+91'
    }
  }

  componentDidMount () {
    const countries = require('countryCodes.json')

    this.con = countries['countries']

    this.list = this.con
  }

  selectCountry () {
    this.setState({
      isVisible: true
    })
  }

  closeOverlay = () => this.setState({ isVisible: false })

  selectedCountry (item) {
    this.setState({
      isVisible: false,

      emoji: item.emoji,

      code: item.phone
    })
  }

  keyExtractor = (item, index) => index.toString()

  renderItem = ({ item }) => (
    <ListItem
      title={item.name}
      subtitle={item.phone}
      leftAvatar={{ title: item.emoji }}
      onPress={() => this.selectedCountry(item)}
      bottomDivider
    />
  )

  updateSearch = search => {
    this.list = this.con.filter(item => {
      const itemName = item.name.toLowerCase()

      const itemCode = item.phone.toLowerCase()

      const textData = search.toLowerCase()

      if (itemName.indexOf(textData) > -1 || itemCode.indexOf(textData) > -1)
        return true
    })

    this.setState({ search })
  }

  inputTextChange = text => {
    const number = this.state.code + text

    this.props.onChangeText(number)
  }

  render () {
    const { search } = this.state

    return (
      <View style={styles.container}>
        <View style={styles.buttonViewStyle}>
          <Button
            buttonStyle={styles.buttonStyle}
            titleStyle={styles.buttonTitleStyle}
            title={this.state.emoji + ' ' + this.state.code}
            onPress={() => this.selectCountry()}
            containerStyle={styles.buttonContainerStyle}
          />
        </View>

        <View style={styles.inputViewStyle}>
          <Input
            keyboardType='number-pad'
            placeholder={this.props.placeholder}
            inputStyle={styles.inputStyle}
            containerStyle={styles.inputContainerStyle}
            onChangeText={text => this.inputTextChange(text)}
            errorMessage={this.props.errorMessage}
          />
        </View>

        <Overlay
          fullScreen
          isVisible={this.state.isVisible}
          onBackdropPress={this.closeOverlay}
        >
          <View>
            <Icon
              name='close'
              containerStyle={styles.iconContainerStyle}
              onPress={this.closeOverlay}
            />

            <SearchBar
              placeholder='Search by country or code '
              onChangeText={this.updateSearch}
              value={search}
              containerStyle={styles.searchBarContainerStyle}
              inputContainerStyle={styles.searchBarInputContainerStyle}
              inputStyle={styles.searchBarInputStyle}
            />

            <FlatList
              keyboardShouldPersistTaps='handled'
              keyExtractor={this.keyExtractor}
              data={this.list}
              renderItem={this.renderItem}
            />
          </View>
        </Overlay>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  buttonStyle: {
    backgroundColor: 'white',

    height: 50
  },

  buttonTitleStyle: {
    color: 'black',

    fontSize: 20,

    justifyContent: 'center'
  },

  buttonViewStyle: { flex: 0.3 },

  container: {
    alignItems: 'center',

    backgroundColor: 'white',

    flexDirection: 'row',

    margin: 10,

    marginRight: 20
  },

  iconContainerStyle: { height: 50, width: 50 },

  inputStyle: {
    fontSize: 20
  },

  inputViewStyle: {
    alignItems: 'flex-start',

    flex: 0.7,

    justifyContent: 'center',

    marginTop: 20
  },

  searchBarContainerStyle: {
    backgroundColor: 'white',

    borderBottomColor: 'white',

    borderTopColor: 'white'
  },

  searchBarInputContainerStyle: {
    backgroundColor: 'white'
  },

  searchBarInputStyle: {
    color: 'black'
  }
})

Let’s look at the methods, updateSearch method used for updating the search reasults according to typed key word in SearchBar.

closeOverlay is used to close the Overlay on Icon press.

we have included our countryCodes.json file in componentDidMount method.

renderItem and keyExtractor used for listing codes in FlatList and indexing them.

As the name explains selectedCountry and selectCountry methods used for updating the selected and selecting country.

The above is the complete code of FullPhoneNumber.js file. You can also grab the complete code from my github.

Here are the final look screenshots.

That’s it guys. If you have any questions, regarding this tutorial, let’s discuss in the comment section.

Thank you for reading.