discover · compare · collections · requirements · contribute · feed · watching · stats · help with your tokens
AstrOOnauta/react-native-country-select · source
Snapshot 0 · 2026-11-04T12:47:28Z · TypeScript · ISC
Content fingerprint
4eb1d206d35d28f7eeea46c82b58e1fa7cc700bd6c6d8d57d6f4959598d5286aGitHub description at capture
🌍 React Native country picker with flags, search, TypeScript, i18n, and offline support. Lightweight, customizable, and designed with a modern UI.
README at capture
<br>
<div align="center">
<img src="https://astroonauta.github.io/react-native-country-select/lib/assets/images/preview.png" alt="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)">
</div>
<br>
<h1 align="center">React Native Country Select</h1>
<p>
🌍 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.
</p>
<br>
<div align="center">
<a href="https://www.npmjs.com/package/rn-country-select">
<img src="https://img.shields.io/npm/v/rn-country-select.svg?style=flat-square" alt="rn-country-select npm version - React Native country picker">
</a>
<a href="https://www.npmjs.com/package/rn-country-select">
<img src="https://img.shields.io/npm/dt/rn-country-select.svg?style=flat-square&color=success" alt="rn-country-select npm downloads - React Native country picker">
</a>
<a href="https://github.com/AstrOOnauta/react-native-country-select/actions/workflows/test.yml">
<img src="https://img.shields.io/github/actions/workflow/status/AstrOOnauta/react-native-country-select/test.yml?branch=main&style=flat-square&label=tests" alt="rn-country-select tests - React Native country picker"/>
</a>
<a href="https://github.com/AstrOOnauta/react-native-country-select">
<img src="https://img.shields.io/github/stars/AstrOOnauta/react-native-country-select?style=flat-square&color=success" alt="GitHub stars - React Native country select"/>
</a>
<a href="https://github.com/AstrOOnauta/react-native-country-select/issues">
<img src="https://img.shields.io/github/issues/AstrOOnauta/react-native-country-select?style=flat-square&color=blue" alt="GitHub issues - React Native country picker"/>
</a>
<a href="https://github.com/AstrOOnauta/react-native-country-select/pulls">
<img src="https://img.shields.io/github/issues-pr/AstrOOnauta/react-native-country-select?style=flat-square&color=blue" alt="GitHub pull requests - rn-country-select"/>
</a>
<a href="LICENSE.md">
<img src="https://img.shields.io/:license-isc-yellow.svg?style=flat-square" alt="ISC License"/>
</a>
</div>
<br>
<div align="center">
<a href="https://www.buymeacoffee.com/astroonautadev" target="_blank">
<img src="https://survivingmexico.files.wordpress.com/2018/07/button-gif.gif" alt="Buy Me A Coffee - Support rn-country-select" style="height: auto !important;width: 60% !important;">
</a>
</div>
<br>
## Features
- 📱 **Cross-Platform** – Works seamlessly on **iOS, Android and Web**;
- 🧩 **Flexible Integration** – Supports both **React Native CLI & Expo**;
- 🎨 **Modern UI** - Custom component with sleek design and dark mode;
- 👨💻 **Component Versatility** - Works with **functional & class components**;
- 🈶 **Internationalization** - Supports **33 languages**, accepts both **ISO 639-1** (`pt`, `en`, `es`) and **ISO 639-2** (`por`, `eng`, `spa`);
- 🔍 **Smart search** - Search by name (diacritic-insensitive), calling code, flag, alpha-2 (`BR`) and alpha-3 (`BRA`);
- 🔠 **Alphabet filter** - Jump-to-letter sidebar;
- ⭐ **Popular section, whitelist & blacklist** of countries;
- 🟢 **Offline-first** - Full ISO 3166-1 dataset bundled, no network calls;
- 🧪 **Test Ready** – Smooth testing integration with stable `testID`s per country;
- ♿ **Accessibility** – Accessibility standards to screen readers.
<br>
## Try it out
- [Demo](https://snack.expo.dev/rn-country-select)
<br>
## Installation
To use this library, make sure you have **rn-country-select** installed along with its required dependency **react-native-safe-area-context**:
```bash
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:
```bash
npx pod-install ios
```
<br>
## Additional config to WEB
- ### Using React Native CLI:
Create a `react-native.config.js` file at the root of your react-native project with:
```bash
module.exports = {
project: {
ios: {},
android: {},
},
assets: [
'./node_modules/rn-country-select/lib/assets/fonts',
],
};
```
Then link the font to your native projects with:
```bash
npx react-native-asset
```
- ### Using Expo:
1. Install [expo-fonts](https://docs.expo.dev/versions/latest/sdk/font/): `npx expo install expo-font`;
2. Initialize the `expo-font`:
```bash
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.
<br>
## Basic Usage
- Class Component
```jsx
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={{ flex: 1 }}>
<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>
);
}
}
```
<br>
- Function Component
```jsx
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={{
flex: 1,
}}
>
<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>
);
}
```
<br>
- Typescript
```tsx
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={{
flex: 1,
}}
>
<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>
);
}
```
<br>
- Multi Select Country
```tsx
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={{
flex: 1,
}}
>
<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>
);
}
```
<br>
### Modal Styles ([modalStyles](https://github.com/AstrOOnauta/react-native-country-select/blob/main/lib/interface/countrySelectStyles.ts))
| 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 |
<br>
## CountrySelect Props ([countrySelectProps](https://github.com/AstrOOnauta/react-native-country-select/blob/main/lib/interface/countrySelectProps.ts))
| 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](lib/interfaces/country.ts)) => void | Yes | - | Callback function called when a country is selected |
| modalType | 'bottomSheet' \| 'popup' | No | 'bottomSheet' | Type of modal to display |
| countrySelectStyle | [ICountrySelectStyle](lib/interfaces/countrySelectStyles.ts) | No | - | Custom styles for the country picker |
| isMultiSelect | boolean | No | false | Whether the user can select multiple options |
| selectedCountries | [ICountry[]](lib/interfaces/country.ts) | 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[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to show (whitelist) |
| hiddenCountries | [ICountryCca2[]](lib/interfaces/countryCca2.ts) | No | [] | Array of country codes to hide (blacklist) |
| theme | 'light' \| 'dark' | No | 'light' | Theme for the country picker |
| language | [ICountrySelectLanguages](lib/interfaces/countrySelectLanguages.ts) | 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](lib/interfaces/country.ts)) => ReactElement | No | - | Custom component for country items |
| sectionTitleComponent | (item: [ISectionTitle](lib/interfaces/sectionTitle.ts)) => ReactElement | No | - | Custom component for section titles |
| closeButtonComponent | () => ReactElement | No | - | Custom component for closeButton |
| customFlag | (country: [ICountry](lib/interfaces/country.ts)) => 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 |
<br>
### 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 |
<br>
## 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.
```js
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');
```
<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
- `accessibilityLabelBackdrop`: Accessibility label for the backdrop;
- `accessibilityHintBackdrop`: Accessibility hint for the backdrop;
- `accessibilityLabelCloseButton`: Accessibility label for the close button;
- `accessibilityHintCloseButton`: Accessibility hint for the close button;
- `accessibilityLabelSearchInput`: Accessibility label for the search input;
- `accessibilityHintSearchInput`: Accessibility hint for the search input;
- `accessibilityLabelCountriesList`: Accessibility label for the countries list;
- `accessibilityHintCountriesList`: Accessibility hint for the countries list;
- `accessibilityLabelCountryItem`: Accessibility label for individual country items;
- `accessibilityHintCountryItem`: Accessibility hint for individual country;
- `accessibilityLabelAlphabetFilter`: Accessibility label for alphabet filter list;
- `accessibilityHintAlphabetFilter`: Accessibility hint for alphabet filter list;
- `accessibilityLabelAlphabetLetter`: Accessibility label for individual alphabet filter letter;
- `accessibilityHintAlphabetLetter`: Accessibility hint for individual alphabet filter letter.
<br>
## Contributing
Thank you for considering contributing to **rn-country-select**!
- Fork or clone this repository
```bash
$ git clone https://github.com/AstrOOnauta/react-native-country-select.git
```
- Repair, Update and Enjoy 🛠️🚧⚙️
- Create a new PR to this repository
<br>
## Credits
@mledoze for the [countries data](https://github.com/mledoze/countries)
## License
[ISC](LICENSE.md)
<br>
<div align="center">
<br>
Thanks for stopping by! 😁
<br>
</div>