Telephone number input React component with country selection, validation, and formatting capabilities
—
Specialized React Phone Number Input components designed for seamless integration with popular React frameworks and form libraries. These components maintain the same core functionality while providing framework-specific APIs and behaviors.
Components specifically designed for React Hook Form integration with built-in field registration and validation support.
/**
* React Hook Form compatible phone input with country selection
* Integrates directly with useForm() hook and Controller component
*/
interface ReactHookFormProps<FormValues extends FieldValues> {
/** Field name for form registration (required) */
name: string;
/** Default phone number value in E.164 format */
defaultValue?: string;
/** React Hook Form control object from useForm() */
control?: Control<FormValues>;
/** Validation rules object */
rules?: {
required?: boolean | string;
validate?: (value: string) => boolean | string;
pattern?: RegExp;
minLength?: number;
maxLength?: number;
[key: string]: any;
};
/** Unregister field when component unmounts */
shouldUnregister?: boolean;
/** All standard phone input props */
defaultCountry?: Country;
placeholder?: string;
disabled?: boolean;
countries?: Country[];
labels?: Labels;
className?: string;
style?: object;
onCountryChange?(country?: Country): void;
// ... all other PhoneInput props supported
}
declare const PhoneInputWithCountrySelect: <FormValues extends FieldValues = FieldValues>(
props: ReactHookFormProps<FormValues>
) => JSX.Element;Usage Examples:
import React from "react";
import { useForm, Controller } from "react-hook-form";
import PhoneInput from "react-phone-number-input/react-hook-form";
import "react-phone-number-input/style.css";
interface FormData {
phoneNumber: string;
name: string;
}
// Basic React Hook Form integration
function ReactHookFormExample() {
const { control, handleSubmit, formState: { errors } } = useForm<FormData>();
const onSubmit = (data: FormData) => {
console.log('Form data:', data);
console.log('Phone number:', data.phoneNumber); // E.164 format
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<PhoneInput
name="phoneNumber"
control={control}
defaultCountry="US"
placeholder="Enter phone number"
rules={{
required: "Phone number is required",
validate: (value) =>
value && value.length > 5 || "Please enter a valid phone number"
}}
/>
{errors.phoneNumber && (
<span className="error">{errors.phoneNumber.message}</span>
)}
<button type="submit">Submit</button>
</form>
);
}
// With FormProvider (no control prop needed)
function FormProviderExample() {
const methods = useForm<FormData>();
return (
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(console.log)}>
<PhoneInput
name="phoneNumber"
defaultCountry="US"
rules={{ required: true }}
/>
</form>
</FormProvider>
);
}
// Custom validation
function CustomValidationExample() {
const { control, handleSubmit } = useForm<FormData>();
const validatePhoneNumber = (value: string) => {
if (!value) return "Phone number is required";
if (!value.startsWith("+1")) return "Please enter a US phone number";
if (value.length < 12) return "Phone number appears incomplete";
return true;
};
return (
<form onSubmit={handleSubmit(console.log)}>
<PhoneInput
name="phoneNumber"
control={control}
defaultCountry="US"
countries={["US", "CA"]}
rules={{ validate: validatePhoneNumber }}
/>
</form>
);
}Input-only version for React Hook Form without country selection.
/**
* React Hook Form compatible input-only phone component
* Provides the same React Hook Form integration without country dropdown
*/
interface ReactHookFormInputProps<FormValues extends FieldValues>
extends ReactHookFormProps<FormValues> {
/** Specific country for national formatting */
country?: Country;
/** Force international format */
international?: boolean;
/** Include country calling code when international=true */
withCountryCallingCode?: boolean;
/** Default country for ambiguous numbers */
defaultCountry?: Country;
/** Custom input component */
inputComponent?: React.ElementType;
/** Enable smart caret positioning */
smartCaret?: boolean;
}
declare const PhoneInput: <FormValues extends FieldValues = FieldValues>(
props: ReactHookFormInputProps<FormValues>
) => JSX.Element;Usage Example:
import PhoneInput from "react-phone-number-input/react-hook-form-input";
function ReactHookFormInputExample() {
const { control, handleSubmit } = useForm();
return (
<form onSubmit={handleSubmit(console.log)}>
<PhoneInput
name="phoneNumber"
control={control}
country="US"
placeholder="(555) 123-4567"
rules={{ required: "Phone number is required" }}
/>
</form>
);
}Core versions requiring manual metadata for smaller bundle sizes.
// React Hook Form with country select (core)
import PhoneInput from "react-phone-number-input/react-hook-form-core";
// React Hook Form input-only (core)
import PhoneInput from "react-phone-number-input/react-hook-form-input-core";
interface ReactHookFormCoreProps<FormValues>
extends ReactHookFormProps<FormValues> {
/** libphonenumber-js metadata object (required) */
metadata: Metadata;
/** Localization labels (required) */
labels: Labels;
}Specialized component for React Native applications.
/**
* React Native compatible phone input component
* Optimized for mobile interfaces and React Native TextInput
*/
interface ReactNativeInputProps {
/** Phone number value in E.164 format */
value?: string;
/** Called when phone number changes */
onChange(value?: string): void;
/** Specific country for national formatting */
country?: Country;
/** Force international format */
international?: boolean;
/** Include country calling code */
withCountryCallingCode?: boolean;
/** Default country for ambiguous numbers */
defaultCountry?: Country;
/** Custom TextInput component */
inputComponent?: React.ElementType;
/** React Native TextInput props */
placeholder?: string;
editable?: boolean;
autoFocus?: boolean;
keyboardType?: 'phone-pad' | 'number-pad' | 'default';
returnKeyType?: string;
onFocus?(event: any): void;
onBlur?(event: any): void;
style?: any;
// ... other React Native TextInput props
}
declare const PhoneInput: React.ForwardRefExoticComponent<ReactNativeInputProps>;Usage Example:
import React, { useState } from "react";
import { View } from "react-native";
import PhoneInput from "react-phone-number-input/react-native-input";
function ReactNativeExample() {
const [phoneNumber, setPhoneNumber] = useState();
return (
<View>
<PhoneInput
value={phoneNumber}
onChange={setPhoneNumber}
defaultCountry="US"
placeholder="Enter phone number"
keyboardType="phone-pad"
style={{
height: 40,
borderColor: 'gray',
borderWidth: 1,
paddingHorizontal: 10
}}
/>
</View>
);
}Framework integrations provide proper TypeScript support for form values.
// React Hook Form field values constraint
interface FieldValues {
[key: string]: any;
}
// Default form values type
type DefaultFormValues = FieldValues;
// Control type from React Hook Form
interface Control<FormValues extends FieldValues> {
register: (name: keyof FormValues, options?: any) => any;
unregister: (name: keyof FormValues) => void;
formState: FormState<FormValues>;
watch: (name?: keyof FormValues) => any;
// ... other Control methods
}Framework integrations handle validation and error states consistently.
// Validation rules interface
interface ValidationRules {
required?: boolean | string;
min?: number | { value: number; message: string };
max?: number | { value: number; message: string };
minLength?: number | { value: number; message: string };
maxLength?: number | { value: number; message: string };
pattern?: RegExp | { value: RegExp; message: string };
validate?:
| ((value: any) => boolean | string)
| Record<string, (value: any) => boolean | string>;
}
// Form state for error handling
interface FormState<FormValues> {
errors: Record<keyof FormValues, { message?: string; type?: string }>;
isDirty: boolean;
isValid: boolean;
isSubmitting: boolean;
// ... other form state properties
}Validation Examples:
// Phone number specific validation
const phoneValidationRules = {
required: "Phone number is required",
validate: {
validFormat: (value: string) =>
!value || value.startsWith('+') || "Phone number must be in international format",
usNumber: (value: string) =>
!value || value.startsWith('+1') || "Please enter a US phone number",
minLength: (value: string) =>
!value || value.length >= 12 || "Phone number appears to be too short"
}
};
function ValidationExample() {
const { control, formState: { errors } } = useForm();
return (
<>
<PhoneInput
name="phoneNumber"
control={control}
rules={phoneValidationRules}
defaultCountry="US"
/>
{errors.phoneNumber && (
<span className="error">
{errors.phoneNumber.message}
</span>
)}
</>
);
}Framework integrations support the shouldUnregister option for proper form cleanup.
interface UnregisterBehavior {
/**
* Controls whether field value is retained when component unmounts
* true: field is unregistered and value is removed (recommended)
* false: field value is retained even after unmount
*/
shouldUnregister?: boolean;
}This affects form behavior when phone input components are conditionally rendered or removed from the DOM.
Install with Tessl CLI
npx tessl i tessl/npm-react-phone-number-input