Props by Example
Every prop of <PhoneInput />, grouped by what you are trying to do, with a snippet you
can paste. For types and defaults, see the Props API table.
Phone number & country
Controlled — you own the state
const [phone, setPhone] = useState('');
const [country, setCountry] = useState<ICountry | null>(null);
<PhoneInput
value={phone}
onChangePhoneNumber={setPhone}
country={country}
onChangeCountry={setCountry}
/>;
Uncontrolled — read it at submit time
const ref = useRef<IPhoneInputRef>(null);
<PhoneInput ref={ref} />;
// later
ref.current?.internationalPhoneNumber; // '+5511912345678'
Full ref surface in the Ref API.
Starting country
<PhoneInput defaultCountry="US" />
ISO 3166-1 alpha-2. Falls back to 'BR' when omitted.
Starting phone number
<PhoneInput defaultPhoneNumber="+12505550199" />
Pass an E.164 number — + + calling code + area
code + number — and the country, flag and mask are set from it. defaultValue is the
deprecated alias.
:::note Both react to prop changes
Change defaultCountry after mount and the country switches — and the typed digits are
cleared, since they no longer fit the new country's format. Change defaultPhoneNumber
and the number is re-applied through the smart-paste pipeline.
When defaultPhoneNumber is set, defaultCountry is ignored: the country comes from
the number itself.
:::
Mask & placeholder
Custom mask
<PhoneInput customMask="(###) ###-####" />
# is a digit slot; everything else is literal. Overrides the country's own mask for
every country, so use it with defaultCountry + modalDisabled for single-country
forms.
Placeholder
// default: a real example number for the selected country
<PhoneInput placeholderType="number" />
// legacy translated text ("Insert your phone number", per `language`)
<PhoneInput placeholderType="text" />
// your own text — wins over placeholderType
<PhoneInput placeholder="Work phone" />
Placeholder and selection colors
<PhoneInput
phoneInputPlaceholderTextColor="#9ca3af"
phoneInputSelectionColor="#2563eb"
/>
Validation & line type
<PhoneInput
onValidationChange={(isValid, type, country) => setCanSubmit(isValid)}
onPhoneNumberTypeChange={(type) => setIsMobile(type === 'MOBILE')}
/>
Both fire only when the value actually changes — details and the standalone validators in the Validation guide.
Filtering the country list
// allow-list: nothing else is selectable
<PhoneInput visibleCountries={['BR', 'PT', 'AO', 'MZ']} />
// deny-list
<PhoneInput hiddenCountries={['RU', 'KP']} />
// pinned to the top, above the full list
<PhoneInput popularCountries={['BR', 'US', 'PT']} />
// rename the two sections
<PhoneInput
popularCountries={['BR', 'US']}
modalPopularCountriesTitle="Most used"
modalAllCountriesTitle="Everything else"
/>
// drop the section headers entirely
<PhoneInput modalSectionTitleDisabled />
Locking the input
// nothing is editable
<PhoneInput disabled />
// number is editable, country is frozen
<PhoneInput defaultCountry="US" modalDisabled />
Neither prop applies a style of its own — see styling the disabled state.
Language
<PhoneInput language="pt" /> // ISO 639-1
<PhoneInput language="por" /> // ISO 639-2 — same thing
Translates country names, section titles, the search placeholder and the not-found message. 33 languages.
Appearance
<PhoneInput
theme="dark" // 'light' | 'dark'
rtl // flag block moves to the right
allowFontScaling={false} // ignore OS font-size setting
phoneInputStyles={{container: {borderRadius: 12}}}
modalStyles={{content: {backgroundColor: '#111827'}}}
/>
Every style key is listed in Theming & Styles.
Replacing the caret and the flag
<PhoneInput
customCaret={() => <Icon name="chevron-down" size={20} />}
customFlag={(country) => <Image source={flags[country.cca2]} />}
/>
customFlag also removes the need for the
flag emoji font.
Modal presentation
<PhoneInput
modalType="bottomSheet" // 'bottomSheet' | 'popup'
isFullScreen={false}
initialBottomsheetHeight="60%" // number (px) or percentage string
minBottomsheetHeight="40%"
maxBottomsheetHeight="90%"
/>
modalType defaults to 'popup' on Web and 'bottomSheet' on iOS/Android.
The three height props apply to bottomSheet only.
Showing and hiding modal pieces
<PhoneInput
showModalSearchInput={false} // no search field
showModalAlphabetFilter // A–Z rail on the side
showModalCloseButton
showModalScrollIndicator={false}
/>
Modal search field
<PhoneInput
modalSearchInputPlaceholder="Search country"
modalSearchInputPlaceholderTextColor="#9ca3af"
modalSearchInputSelectionColor="#2563eb"
modalSearchInputFocusedBorderColor="#2563eb"
modalNotFoundCountryMessage="No country matches that"
/>
Leave the two text props out and they are translated from language.
Backdrop and closing
<PhoneInput
disabledModalBackdropPress // tapping outside won't close
removedModalBackdrop // no dim layer at all
onModalBackdropPress={(closeModal) => {
if (hasUnsavedChanges) return; // veto the close
closeModal();
}}
onModalRequestClose={() => analytics.track('country_modal_closed')}
/>
onModalRequestClose also covers the Android hardware back button.
Replacing modal components
<PhoneInput
modalDragHandleIndicatorComponent={() => <View style={styles.handle} />}
modalSectionTitleComponent={(item) => <Text style={styles.h2}>{item.title}</Text>}
modalCountryItemComponent={(country) => (
<View style={styles.row}>
<Text>{country.flag}</Text>
<Text>{country.name.common}</Text>
<Text>{country.idd.root}</Text>
</View>
)}
modalCloseButtonComponent={() => <Text>Done</Text>}
/>
Accessibility
Eighteen label/hint props, one pair per interactive element:
<PhoneInput
accessibilityLabelPhoneInput="Phone number"
accessibilityHintPhoneInput="Enter your number without the country code"
accessibilityLabelCountriesButton="Select country"
accessibilityHintCountriesButton="Opens the country list"
/>
Complete list in the Accessibility guide.
Anything TextInput accepts
PhoneInputProps extends React Native's
TextInputProps, so these all work:
<PhoneInput
autoFocus
onFocus={handleFocus}
onBlur={handleBlur}
returnKeyType="done"
onSubmitEditing={submit}
maxLength={20}
testID="phone-input"
/>
The only two that are not forwarded are value and onChangeText — the component
owns them; use value + onChangePhoneNumber.
Everything at once
<PhoneInput
ref={ref}
theme="dark"
language="pt"
defaultCountry="BR"
popularCountries={['BR', 'PT', 'US']}
hiddenCountries={['RU']}
placeholderType="number"
modalType="bottomSheet"
initialBottomsheetHeight="60%"
showModalAlphabetFilter
onValidationChange={(isValid) => setCanSubmit(isValid)}
onPhoneNumberTypeChange={(type) => setLineType(type)}
phoneInputStyles={{container: {borderRadius: 12}}}
modalStyles={{content: {backgroundColor: '#111827'}}}
accessibilityLabelPhoneInput="Phone number"
autoFocus
testID="phone-input"
/>
Next
- Props API table — types and defaults
- Ref API and
usePhoneInput - FAQ & Troubleshooting