react-native-country-select


rn-country-select preview - React Native country picker, country code selector, dial code dropdown, flag picker with search, multi-select, dark mode and i18n (33 languages)


React Native Country Select

🌍 React Native country picker with flags, search, multi-select, dial codes, TypeScript, full i18n (33 languages, ISO 639-1 & ISO 639-2), and offline support. Lightweight, translations, customizable, and designed with a modern UI.


rn-country-select npm version - React Native country picker rn-country-select npm downloads - React Native country picker GitHub stars - React Native country select GitHub issues - React Native country picker GitHub pull requests - rn-country-select ISC License


Buy Me A Coffee - Support rn-country-select


Features


Try it out


Installation

To use this library, make sure you have rn-country-select installed along with its required dependency react-native-safe-area-context:

npm install rn-country-select react-native-safe-area-context

Since react-native-safe-area-context includes native code, you’ll need to install the iOS pods on macOS to complete the linking:

npx pod-install ios


Additional config to WEB

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

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

Then link the font to your native projects with:

npx react-native-asset
  1. Install expo-fonts: npx expo install expo-font;
  2. Initialize the expo-font:
  import { useFonts } from 'expo-font';

  ...

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

  ...

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


Basic Usage

import React, { Component } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
import CountrySelect from 'rn-country-select';

export default class App extends Component {
  countryRef = null;

  constructor(props) {
    super(props);
    this.state = {
      showPicker: false,
      country: null,
    };
  }

  handleCountrySelect = (country) => {
    this.setState({ country });
  };

  render() {
    return (
      <View style=>
        <TouchableOpacity
          onPress={() => this.setState({ showPicker: true })}
        >
          <Text>Select Country</Text>
        </TouchableOpacity>
        <Text>
          Country:{' '}
          {`${this.state.selectedCountry?.name?.common} (${this.state.selectedCountry?.cca2})`}
        </Text>

        <CountrySelect
          visible={this.state.showPicker}
          onClose={() => this.setState({ showPicker: false })}
          onSelect={this.handleCountrySelect}
        />
      </View>
    );
  }
}


import React, { useState } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';

import CountrySelect from 'rn-country-select';

export default function App() {
  const [showPicker, setShowPicker] = useState(false);
  const [selectedCountry, setSelectedCountry] = useState(null);

  const handleCountrySelect = (country) => {
    setSelectedCountry(country);
  };

  return (
    <View
      style=
    >
      <TouchableOpacity onPress={() => setShowPicker(true)}>
        <Text>Select Country</Text>
      </TouchableOpacity>
      <Text>
        Country:{' '}
        {`${selectedCountry?.name?.common} (${selectedCountry?.cca2})`}
      </Text>

      <CountrySelect
        visible={showPicker}
        onClose={() => setShowPicker(false)}
        onSelect={handleCountrySelect}
      />
    </View>
  );
}


import React, { useState } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';

import CountrySelect, { ICountry } from 'rn-country-select';

export default function App() {
  const [showPicker, setShowPicker] = useState<boolean>(false);
  const [selectedCountry, setSelectedCountry] =
    useState<ICountry | null>(null);

  const handleCountrySelect = (country: ICountry) => {
    setSelectedCountry(country);
  };

  return (
    <View
      style=
    >
      <TouchableOpacity onPress={() => setShowPicker(true)}>
        <Text>Select Country</Text>
      </TouchableOpacity>
      <Text>
        Country:{' '}
        {`${selectedCountry?.name?.common} (${selectedCountry?.cca2})`}
      </Text>

      <CountrySelect
        visible={showPicker}
        onClose={() => setShowPicker(false)}
        onSelect={handleCountrySelect}
      />
    </View>
  );
}


import React, { useState } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';

import CountrySelect, { ICountry } from 'rn-country-select';

export default function App() {
  const [showPicker, setShowPicker] = useState<boolean>(false);
  const [selectedCountries, setSelectedCountries] = useState<
    ICountry[]
  >([]);

  const handleCountrySelect = (countries: ICountry[]) => {
    setSelectedCountries(countries);
  };

  return (
    <View
      style=
    >
      <TouchableOpacity onPress={() => setShowPicker(true)}>
        <Text>Select Countries</Text>
      </TouchableOpacity>
      <Text>Countries: {selectedCountries.length}</Text>

      <CountrySelect
        visible={showPicker}
        isMultiSelect
        selectedCountries={selectedCountries}
        onSelect={handleCountrySelect}
        onClose={() => setShowPicker(false)}
      />
    </View>
  );
}


Property Type Description
backdrop ViewStyle Modal background overlay
container ViewStyle Modal main container
content ViewStyle Modal content area
dragHandleContainer ViewStyle Drag Handle area
dragHandleIndicator ViewStyle Drag Handle Indicator
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
alphabetContainer ViewStyle Alphabet filter container
alphabetLetter ViewStyle Alphabet letter item
alphabetLetterText TextStyle Alphabet letter text
alphabetLetterActive ViewStyle Active letter state
alphabetLetterDisabled ViewStyle Disabled letter state
alphabetLetterTextActive TextStyle Active letter text
alphabetLetterTextDisabled TextStyle Disabled letter text


CountrySelect Props (countrySelectProps)

Prop Type Required Default Description
visible boolean Yes false Controls the visibility of the country picker modal
onClose () => void Yes - Callback function called when the modal is closed
onSelect (country: ICountry) => void Yes - Callback function called when a country is selected
modalType ‘bottomSheet’ | ‘popup’ No ‘bottomSheet’ Type of modal to display
countrySelectStyle ICountrySelectStyle No - Custom styles for the country picker
isMultiSelect boolean No false Whether the user can select multiple options
selectedCountries ICountry[] No - Array of countries to show in multi select mode
isFullScreen boolean No false Whether the modal should be full screen
popularCountries string[] No [] Array of country codes to show in popular section
visibleCountries ICountryCca2[] No [] Array of country codes to show (whitelist)
hiddenCountries ICountryCca2[] No [] Array of country codes to hide (blacklist)
theme ‘light’ | ‘dark’ No ‘light’ Theme for the country picker
language ICountrySelectLanguages No ‘eng’ Language for country names. Accepts ISO 639-1 (pt) or ISO 639-2 (por)
showSearchInput boolean No true Whether to show the search input field
showAlphabetFilter boolean No false Whether to show the alphabetic filter on modal
searchPlaceholder string No ‘Search country…’ Placeholder text for search input
searchPlaceholderTextColor string No ‘#00000080’ Placeholder text color for search input
searchSelectionColor string No - Passed to the search TextInput as selectionColor (cursor and selection highlight)
searchFocusedBorderColor string No - Border color of the search field when focused (defaults: light #3B82F6, dark #60A5FA)
minBottomsheetHeight number | string No 30% Minimum height for bottom sheet modal
maxBottomsheetHeight number | string No 80% Maximum height for bottom sheet modal
initialBottomsheetHeight number | string No 50% Initial height for bottom sheet modal
disabledBackdropPress boolean No false Whether to disable backdrop press to close
removedBackdrop boolean No false Whether to remove the backdrop completely
onBackdropPress (closeModal: () => void) => void No - Custom callback for backdrop press
dragHandleIndicatorComponent () => ReactElement - - Custom component for drag handle indicator on bottom sheet
countryItemComponent (item: ICountry) => ReactElement No - Custom component for country items
sectionTitleComponent (item: ISectionTitle) => ReactElement No - Custom component for section titles
closeButtonComponent () => ReactElement No - Custom component for closeButton
customFlag (country: ICountry) => ReactElement No - Custom render function for country flags. Returns rendered element in selected country
showCloseButton boolean No false Whether to show the close button
popularCountriesTitle string No ‘Popular Countries’ Popular Countries section title
allCountriesTitle string No ‘All Countries’ All Countries section title
showsVerticalScrollIndicator boolean No false Shows the vertical scroll indicator on the countries list
countryNotFoundMessage string No “No countries found” Country not found in search
allowFontScaling boolean No true Whether to allow font scaling for text elements


Supported Languages

The language prop accepts both ISO 639-1 (2-letter) and ISO 639-2 (3-letter) codes:

ISO 639-1 ISO 639-2 Language
ar ara Arabic
be bel Belarusian
br bre Breton
bg bul Bulgarian
cs ces Czech
de deu German
el ell Greek
en eng English (default)
et est Estonian
fi fin Finnish
fr fra French
he heb Hebrew
hr hrv Croatian
hu hun Hungarian
it ita Italian
ja jpn Japanese
ko kor Korean
nl nld Dutch
fa per Persian
pl pol Polish
pt por Portuguese
ro ron Romanian
ru rus Russian
sk slk Slovak
es spa Spanish
sr srp Serbian
sv swe Swedish
tr tur Turkish
uk ukr Ukrainian
ur urd Urdu
zh zho Chinese
zh-Hans zho-Hans Simplified Chinese
zh-Hant zho-Hant Traditional Chinese


Testing

When utilizing this package, you may need to target the CountrySelect component in your automated tests. To facilitate this, we provide a testID props for the CountrySelect 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 CountrySelect elements within your tests, ensuring a robust and reliable testing experience.

const countrySelectModalContainer = getByTestId(
  'countrySelectContainer'
);
const countrySelectModalContent = getByTestId('countrySelectContent');
const countrySelectBackdrop = getByTestId('countrySelectBackdrop');
const countrySelectList = getByTestId('countrySelectList');
const countrySelectSearchInput = getByTestId(
  'countrySelectSearchInput'
);
const countrySelectCloseButton = getByTestId(
  'countrySelectCloseButton'
);
const countrySelectAlphabetFilter = getByTestId(
  'countrySelectAlphabetFilter'
);
const countrySelectSectionTitle = getByTestId(
  'countrySelectSectionTitle'
);

// Per-country (suffix is the cca2 code)
const brazilItem = getByTestId('countrySelectItem-BR');
const brazilFlag = getByTestId('countrySelectItemFlag-BR');
const brazilCallingCode = getByTestId(
  'countrySelectItemCallingCode-BR'
);
const brazilName = getByTestId('countrySelectItemName-BR');


Accessibility

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

Custom Accessibility Props Available


Contributing

Thank you for considering contributing to rn-country-select!

  $ git clone https://github.com/AstrOOnauta/react-native-country-select.git


Credits

@mledoze for the countries data

License

ISC



Thanks for stopping by! 😁