Create an OTP Generator and Validator App using React-Native
One-time passwords (OTPs) have become a popular choice for enhancing the security of various online services and applications. In this article, we'll explore how to create an OTP Generator and Validator App using React Native, a popular framework for building cross-platform mobile applications.
To give you a better idea of what we’re going to create, let’s watch a demo video.
Demo Video
Prerequisites:
Step-by-Step Implementation
Step 1: Create a React Native Project
Now, create a project with the following command.
npx create-expo-app app-name --template
Note: Replace the app-name with your app name for example : react-native-demo-app
Next, you might be asked to choose a template. Select one based on your preference as shown in the image below. I am selecting the blank template because it will generate a minimal app that is as clean as an empty canvas in JavaScript.

It completes the project creation and displays a message: "Your Project is ready!" as shown in the image below.

Now go into your project folder, i.e., react-native-demo
cd app-name
Project Structure:

Step 2: Run Application
Start the server by using the following command.
npx expo start
Then, the application will display a QR code.
- For the Android users,
- For the Android Emulator, press "a" as mentioned in the image below.
- For the Physical Device, download the "Expo Go" app from the Play Store. Open the app, and you will see a button labeled "Scan QR Code." Click that button and scan the QR code; it will automatically build the Android app on your device.
- For iOS users, simply scan the QR code using the Camera app.
- If you're using a web browser, it will provide a local host link that you can use as mentioned in the image below.

Step 3: Start Coding
Approach:
Code implements an OTP (One-Time Password) generator and validator interface. It uses the useState hook to manage the OTP, user input, and validation status. The app allows users to generate and validate OTPs. It conditionally renders the OTP box and displays the generated OTP inside a bordered box when the "Generate OTP" button is clicked. The user can enter the OTP in the input field and click the "Validate OTP" button to check its validity. The code also includes styles for the components, such as buttons, input fields, and text elements, with appropriate visual feedback for valid and invalid OTPs. Let's explore the code in detailed.
- Import libraries: Import required libraries at the top of the file.
// Import useState hook from React
import { useState } from 'react';
// Import required components from react-native
// Import core components from react-native for building UI
import {
View, // Container component for layout
Text, // Component for displaying text
TextInput, // Input field for user text entry
TouchableOpacity, // Button-like component for touch interactions
StyleSheet // Utility for creating component styles
} from 'react-native';
- StyleSheet: Create a StyleSheet to style components like container, box, title, etc.
// Define styles for the components
const styles = StyleSheet.create({
container: {
flex: 1, // Take full height
justifyContent: 'center', // Center vertically
alignItems: 'center', // Center horizontally
},
box: {
width: '80%', // 80% of screen width
backgroundColor: '#FFF', // White background
borderRadius: 10, // Rounded corners
padding: 20, // Padding inside box
shadowColor: '#000', // Shadow color
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25, // Shadow opacity
shadowRadius: 3.84, // Shadow blur radius
elevation: 5, // Android shadow
},
title: {
fontSize: 24, // Large font size
marginBottom: 20, // Space below title
},
button: {
backgroundColor: '#007AFF', // Blue background
paddingHorizontal: 30, // Horizontal padding
paddingVertical: 15, // Vertical padding
borderRadius: 5, // Rounded corners
marginTop: 20, // Space above button
},
buttonText: {
color: '#FFF', // White text
fontSize: 18, // Medium font size
},
input: {
borderWidth: 1, // Border width
borderColor: '#007AFF', // Border color
borderRadius: 5, // Rounded corners
paddingHorizontal: 10, // Horizontal padding
paddingVertical: 5, // Vertical padding
marginTop: 20, // Space above input
width: '100%', // Full width
},
otpBox: {
marginTop: 20, // Space above OTP box
backgroundColor: 'white', // White background
borderRadius: 5, // Rounded corners
padding: 10, // Padding inside box
borderWidth: 2, // Border width
borderColor: 'grey', // Border color
},
otp: {
fontSize: 24, // Large font for OTP
},
validText: {
fontSize: 20, // Font size for valid message
color: 'green', // Green color
marginTop: 20, // Space above message
},
invalidText: {
fontSize: 20, // Font size for invalid message
color: 'red', // Red color
marginTop: 20, // Space above message
},
});
- Title Text: This title explains what the app does. We use the text "OTP Generator | Validator" to show that the app can generate and validate OTPs (One-Time Passwords).
<Text style={styles.title}>
OTP Generator | Validator {/* Title text */}
</Text>
- Generate OTP Button: This button is used to interact with the user. When the user taps on it, it calls a function called generateOtp, which generates a One-Time Password (OTP). The button is designed by placing a text saying "Generate OTP" inside a TouchableOpacity component.
<TouchableOpacity style={styles.button}
onPress={generateOtp}> {/* Button to generate OTP */}
<Text style={styles.buttonText}>
Generate OTP
</Text>
</TouchableOpacity>
- generateOtp function: This function creates a 6-character OTP (One-Time Password). It uses Math.random and Math.floor to generate the OTP. Then, it updates the otp state variable with the new OTP by using the setOtp function. It also sets the isValid state variable to null by calling setIsValid with null. Finally, it changes the showOtpBox state variable to true by using setShowOtpBox, which means the OTP box will be shown.
// State to store the generated OTP
const [otp, setOtp] = useState('');
// State to store OTP validation result (true/false/null)
const [isValid, setIsValid] = useState(null);
// State to control visibility of the OTP box
const [showOtpBox, setShowOtpBox] = useState(false);
// Function to generate a random 6-character OTP
const generateOtp = () => {
let generatedOtp = ''; // Initialize empty OTP string
const characters =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; // Allowed characters
// Loop to generate 6 random characters
for (let i = 0; i < 6; i++) {
generatedOtp += characters
.charAt(Math
.floor(Math.random() * characters.length)); // Pick a random character
}
setOtp(generatedOtp); // Update OTP state
setIsValid(null); // Reset validation state
setShowOtpBox(true); // Show the OTP box
};
- Display OTP Generated: Display the OTP generated using the following code; it will only display if showOtpBox is true.
// State to store the generated OTP
const [otp, setOtp] = useState('');
// State to control visibility of the OTP box
const [showOtpBox, setShowOtpBox] = useState(false);
{showOtpBox && ( // Conditionally render OTP box
<View style={styles.otpBox}>
<Text style=
{
[styles.otp, { color: 'black' }]
}>
{otp} {/* Display generated OTP */}
</Text>
</View>
)}
- TextInput and validate button: We have a TextInput for users to enter their OTP (One Time Password) and a button to check if the entered OTP matches the one that was generated. The TextInput uses a function called setUserInput to save what the user types in. This updates the userInput state variable so we can see the input. When you click the "Validate OTP" button, it calls a function called validateOtp, which checks if the generated OTP and the user-entered OTP are the same.
// State to store user input for OTP
const [userInput, setUserInput] = useState('');
<TextInput
style={styles.input}
placeholder="Enter OTP" // Placeholder text
value={userInput} // Value bound to userInput state
onChangeText={setUserInput} // Update userInput on change
/>
<TouchableOpacity style={styles.button}
onPress={validateOtp}> {/* Button to validate OTP */}
<Text style={styles.buttonText}>
Validate OTP
</Text>
</TouchableOpacity>
- validateOtp function: This function checks if the generated OTP matches the user's entered OTP by comparing the otp and userInput state variables. If they match, the function sets the isValid variable to true by calling setIsValid with true. If they do not match, it calls setIsValid with false.
// State to store the generated OTP
const [otp, setOtp] = useState('');
// State to store user input for OTP
const [userInput, setUserInput] = useState('');
// State to store OTP validation result (true/false/null)
const [isValid, setIsValid] = useState(null);
// Function to validate the entered OTP
const validateOtp = () => {
if (userInput === otp) { // Check if user input matches OTP
setIsValid(true); // Set validation state to true
} else {
setIsValid(false); // Set validation state to false
}
};
- Display Valid or InValid: After updating the value of isValid, below code will display "Valid OTP" if the isValid is true and "Invalid OTP" if it is false.
{/* Display messages based on the validity status */}
{isValid === true &&
<Text style={styles.validText}>
Valid OTP {/* Message for valid OTP */}
</Text>}
{isValid === false &&
<Text style={styles.invalidText}>
Invalid OTP {/* Message for invalid OTP */}
</Text>}
Now, wrap all design code with a View component, return it from the App component, and place all methods and useStates within the App component. Ensure to export the App.
Complete Source Code
App.js:
// Import useState hook from React
import { useState } from 'react';
// Import required components from react-native
// Import core components from react-native for building UI
import {
View, // Container component for layout
Text, // Component for displaying text
TextInput, // Input field for user text entry
TouchableOpacity, // Button-like component for touch interactions
StyleSheet // Utility for creating component styles
} from 'react-native';
// Define the main App component
const App = () => {
// State to store the generated OTP
const [otp, setOtp] = useState('');
// State to store user input for OTP
const [userInput, setUserInput] = useState('');
// State to store OTP validation result (true/false/null)
const [isValid, setIsValid] = useState(null);
// State to control visibility of the OTP box
const [showOtpBox, setShowOtpBox] = useState(false);
// Function to generate a random 6-character OTP
const generateOtp = () => {
let generatedOtp = ''; // Initialize empty OTP string
const characters =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; // Allowed characters
// Loop to generate 6 random characters
for (let i = 0; i < 6; i++) {
generatedOtp += characters
.charAt(Math
.floor(Math.random() * characters.length)); // Pick a random character
}
setOtp(generatedOtp); // Update OTP state
setIsValid(null); // Reset validation state
setShowOtpBox(true); // Show the OTP box
};
// Function to validate the entered OTP
const validateOtp = () => {
if (userInput === otp) { // Check if user input matches OTP
setIsValid(true); // Set validation state to true
} else {
setIsValid(false); // Set validation state to false
}
};
// Render the UI
return (
<View style={styles.container}> {/* Main container */}
<View style={styles.box}> {/* Inner box for content */}
<Text style={styles.title}>
OTP Generator | Validator {/* Title text */}
</Text>
<TouchableOpacity style={styles.button}
onPress={generateOtp}> {/* Button to generate OTP */}
<Text style={styles.buttonText}>
Generate OTP
</Text>
</TouchableOpacity>
{showOtpBox && ( // Conditionally render OTP box
<View style={styles.otpBox}>
<Text style=
{
[styles.otp, { color: 'black' }]
}>
{otp} {/* Display generated OTP */}
</Text>
</View>
)}
<TextInput
style={styles.input}
placeholder="Enter OTP" // Placeholder text
value={userInput} // Value bound to userInput state
onChangeText={setUserInput} // Update userInput on change
/>
<TouchableOpacity style={styles.button}
onPress={validateOtp}> {/* Button to validate OTP */}
<Text style={styles.buttonText}>
Validate OTP
</Text>
</TouchableOpacity>
{/* Display messages based on the validity status */}
{isValid === true &&
<Text style={styles.validText}>
Valid OTP {/* Message for valid OTP */}
</Text>}
{isValid === false &&
<Text style={styles.invalidText}>
Invalid OTP {/* Message for invalid OTP */}
</Text>}
</View>
</View>
);
};
// Define styles for the components
const styles = StyleSheet.create({
container: {
flex: 1, // Take full height
justifyContent: 'center', // Center vertically
alignItems: 'center', // Center horizontally
},
box: {
width: '80%', // 80% of screen width
backgroundColor: '#FFF', // White background
borderRadius: 10, // Rounded corners
padding: 20, // Padding inside box
shadowColor: '#000', // Shadow color
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25, // Shadow opacity
shadowRadius: 3.84, // Shadow blur radius
elevation: 5, // Android shadow
},
title: {
fontSize: 24, // Large font size
marginBottom: 20, // Space below title
},
button: {
backgroundColor: '#007AFF', // Blue background
paddingHorizontal: 30, // Horizontal padding
paddingVertical: 15, // Vertical padding
borderRadius: 5, // Rounded corners
marginTop: 20, // Space above button
},
buttonText: {
color: '#FFF', // White text
fontSize: 18, // Medium font size
},
input: {
borderWidth: 1, // Border width
borderColor: '#007AFF', // Border color
borderRadius: 5, // Rounded corners
paddingHorizontal: 10, // Horizontal padding
paddingVertical: 5, // Vertical padding
marginTop: 20, // Space above input
width: '100%', // Full width
},
otpBox: {
marginTop: 20, // Space above OTP box
backgroundColor: 'white', // White background
borderRadius: 5, // Rounded corners
padding: 10, // Padding inside box
borderWidth: 2, // Border width
borderColor: 'grey', // Border color
},
otp: {
fontSize: 24, // Large font for OTP
},
validText: {
fontSize: 20, // Font size for valid message
color: 'green', // Green color
marginTop: 20, // Space above message
},
invalidText: {
fontSize: 20, // Font size for invalid message
color: 'red', // Red color
marginTop: 20, // Space above message
},
});
// Export the App component as default
export default App;
Output: