react-native-otp-entry and react-otp-input are UI components designed to handle One-Time Password (OTP) or verification code entry in React applications. react-otp-input is primarily built for React web applications, offering a customizable input field that splits characters into separate boxes. react-native-otp-entry is tailored for React Native mobile environments, focusing on native keyboard handling, auto-fill support, and mobile-specific UX patterns. Both aim to simplify the implementation of secure code entry but target different rendering platforms.
Both react-native-otp-entry and react-otp-input solve the same user problem: entering a short verification code securely. However, they operate in fundamentally different environments. One targets the mobile native ecosystem, while the other targets the web DOM. Choosing the wrong one for your platform will lead to broken builds or poor user experience. Let's compare how they handle input, styling, and platform features.
react-native-otp-entry is built exclusively for React Native.
TextInput components under the hood.keyboardType and autoFill hints.// react-native-otp-entry: Native implementation
import { OTPEntry } from 'react-native-otp-entry';
export default function App() {
return (
<OTPEntry
totalDigits={6}
onTextChange={(text) => console.log(text)}
/>
);
}
react-otp-input is built for React web applications.
<input> elements.// react-otp-input: Web implementation
import OtpInput from 'react-otp-input';
export default function App() {
return (
<OtpInput
numInputs={6}
onChange={(text) => console.log(text)}
renderInput={(props) => <input {...props} />}
/>
);
}
react-native-otp-entry configures the mobile keyboard directly.
keyboardType='numeric' to show the number pad.// react-native-otp-entry: Keyboard config
<OTPEntry
totalDigits={6}
keyboardType="number-pad"
secureTextEntry={false}
onTextChange={(code) => setCode(code)}
/>
react-otp-input relies on HTML input attributes.
type="tel" or inputMode="numeric" for mobile browsers.// react-otp-input: Input mode config
<OtpInput
numInputs={6}
inputType="tel"
inputMode="numeric"
onChange={(code) => setCode(code)}
renderInput={(props) => <input {...props} />}
/>
react-native-otp-entry uses React Native style objects.
style prop accepting a StyleSheet.// react-native-otp-entry: Styling
<OTPEntry
totalDigits={6}
styles={{
digitBox: { borderWidth: 1, borderColor: '#ccc' },
filledBox: { borderColor: '#000' }
}}
onTextChange={(text) => setText(text)}
/>
react-otp-input uses CSS classes or inline styles.
containerStyle or inputStyle props.renderInput.// react-otp-input: Styling
<OtpInput
numInputs={6}
inputStyle={{ border: '1px solid #ccc' }}
containerStyle={{ display: 'flex', gap: '10px' }}
onChange={(text) => setText(text)}
renderInput={(props) => <input {...props} />}
/>
react-native-otp-entry integrates with OS auto-fill.
// react-native-otp-entry: Auto-fill hints
<OTPEntry
totalDigits={6}
textContentType="oneTimeCode"
onTextChange={(text) => setText(text)}
/>
react-otp-input handles clipboard via browser events.
autoComplete="one-time-code" for browser support.// react-otp-input: Auto-complete
<OtpInput
numInputs={6}
autoComplete="one-time-code"
onChange={(text) => setText(text)}
renderInput={(props) => <input {...props} />}
/>
These packages are specialized for OTP flows. Consider alternatives when:
formik or react-hook-form with standard inputs.react-native-otp-text-input.| Feature | react-native-otp-entry | react-otp-input |
|---|---|---|
| Platform | 📱 React Native (iOS/Android) | 🌐 React Web (DOM) |
| Underlying Element | Native TextInput | HTML <input> |
| Styling | React Native StyleSheet | CSS / Inline Styles |
| Auto-Fill | Native OS SMS/Code Fill | Browser autoComplete |
| Keyboard | keyboardType prop | inputMode / type props |
| Paste Support | Native Clipboard | JS Paste Event |
Think in terms of target environment first:
react-native-otp-entry. It leverages native capabilities for SMS auto-fill and keyboard management that web components cannot access.react-otp-input. It is optimized for browser behavior, clipboard pasting, and DOM focus management.Critical Note: Do not attempt to use react-otp-input in a React Native project. It relies on DOM APIs that do not exist in the native runtime. Conversely, react-native-otp-entry will not render in a web browser. Always match the package to your rendering engine.
Choose react-native-otp-entry if you are building a mobile application using React Native. It is optimized for touch interfaces, supports native auto-fill APIs on iOS and Android, and handles soft keyboard interactions correctly. This package is essential when you need the OTP field to integrate seamlessly with mobile OS features like SMS retreival.
Choose react-otp-input if you are developing a web application using React.js. It provides robust support for desktop and mobile browsers, handling clipboard pasting and character separation effectively in a DOM environment. This package is the standard choice for web-based login flows where React Native specific native modules are not available.
react-native-otp-entry is a simple and highly customizable React Native component for entering OTP (One-Time Password) on iOS, Android, and Web. It provides an intuitive and user-friendly interface for inputting one-time passwords in your React Native applications.
Looking for a Phone Number input component? Check out react-native-phone-entry - a simple and fully modifiable Phone Number Input Component for React Native that provides an intuitive interface for entering and validating international phone numbers.

Try out React Native OTP Entry in action on Snack Expo:
or https://snack.expo.dev/@anday013/demo-react-native-otp-entry
Install react-native-otp-entry using npm or yarn:
npm install react-native-otp-entry
# or
yarn add react-native-otp-entry
Import the OtpInput component from react-native-otp-entry:
import { OtpInput } from "react-native-otp-entry";
Render the OtpInput component in your screen/component:
<OtpInput numberOfDigits={6} onTextChange={(text) => console.log(text)} />
Customize the styling as per your requirements:
<OtpInput
numberOfDigits={6}
focusColor="green"
autoFocus={false}
hideStick={true}
placeholder="******"
blurOnFilled={true}
disabled={false}
type="numeric"
secureTextEntry={false}
focusStickBlinkingDuration={500}
onFocus={() => console.log("Focused")}
onBlur={() => console.log("Blurred")}
onTextChange={(text) => console.log(text)}
onFilled={(text) => console.log(`OTP is ${text}`)}
textInputProps={{
accessibilityLabel: "One-Time Password",
}}
textProps={{
accessibilityRole: "text",
accessibilityLabel: "OTP digit",
allowFontScaling: false,
}}
theme={{
containerStyle: styles.container,
pinCodeContainerStyle: styles.pinCodeContainer,
pinCodeTextStyle: styles.pinCodeText,
focusStickStyle: styles.focusStick,
focusedPinCodeContainerStyle: styles.activePinCodeContainer,
placeholderTextStyle: styles.placeholderText,
filledPinCodeContainerStyle: styles.filledPinCodeContainer,
disabledPinCodeContainerStyle: styles.disabledPinCodeContainer,
}}
/>
The react-native-otp-entry component accepts the following props:
| Prop | Type | Description |
|---|---|---|
numberOfDigits | number | The number of digits to be displayed in the OTP entry. |
theme | Theme | Custom styles for each element. (See below) |
textInputProps | TextInputProps | Extra props passed to underlying hidden TextInput (see: https://reactnative.dev/docs/textinput) |
textProps | TextProps | Props passed to the Text component that renders each digit (see: https://reactnative.dev/docs/text) |
autoFocus | boolean | Default: true. Sets autofocus. |
focusColor | ColorValue | The color of the input field border and stick when it is focused. |
placeholder | string | Placeholder value to the input. |
onTextChange | (text: string) => void | A callback function is invoked when the OTP text changes. It receives the updated text as an argument. |
onFilled | (text: string) => void | A callback function is invoked when the OTP input is fully filled. It receives a full otp code as an argument. |
blurOnFilled | boolean | Default: false. Blurs (unfocuses) the input when the OTP input is fully filled. |
hideStick | boolean | Default: false. Hides cursor of the focused input. |
focusStickBlinkingDuration | number | The duration (in milliseconds) for the focus stick to blink. |
disabled | boolean | Default: false. Disables the input |
type | 'alpha' | 'numeric' | 'alphanumeric' | The type of input. 'alpha': letters only, 'numeric': numbers only, 'alphanumeric': letters or numbers. |
secureTextEntry | boolean | Default: false. Obscures the text entered so that sensitive text like PIN stay secure. |
onFocus | () => void | A callback function is invoked when the OTP input is focused. |
onBlur | () => void | A callback function is invoked when the OTP input is blurred. |
| Theme | Type | Description |
|---|---|---|
containerStyle | ViewStyle | Custom styles for the root View. |
pinCodeContainerStyle | ViewStyle | Custom styles for the container that wraps each individual digit in the OTP entry. |
pinCodeTextStyle | TextStyle | Custom styles for the text within each individual digit in the OTP entry. |
placeholderTextStyle | TextStyle | Custom styles for the placeholder text within each individual digit in the OTP entry. |
focusStickStyle | ViewStyle | Custom styles for the focus stick, which indicates the focused input field. |
focusedPinCodeContainerStyle | ViewStyle | Custom styles for the input field when it is focused. |
filledPinCodeContainerStyle | ViewStyle | Custom styles for the input field when it has a value. |
disabledPinCodeContainerStyle | ViewStyle | Custom styles for the input field when it is disabled. |
Note: The ViewStyle and TextStyle types are imported from react-native and represent the style objects used in React Native for views and text, respectively.
Tip: If you have difficulties while applying gap or in any other style property to set a suitable space between the OTP input containers, please set the width in containerStyle to 'auto' or undefined, as it is been set to '100%' by default.
The react-native-otp-entry component exposes these functions with ref:
| Prop | Type | Description |
|---|---|---|
clear | () => void; | Clears the value of the OTP input. |
focus | () => void; | Focus of the OTP input. |
blur | () => void; | Blurs the OTP input. |
setValue | (value: string) => void; | Sets the value of the OTP input. |
This project is licensed under the MIT License.
Contributions are welcome! Please feel free to open issues or submit pull requests.
If you find a bug or have any feature requests, please open an issue :)
If you find this project helpful and want to support my work, consider buying me a coffee! ☕