Building an OTP Input Component in React
A step-by-step guide to creating a 5-digit OTP input with automatic focus management
✅ 1. Initial Setup and State Management
Start by importing essential React hooks and defining component state:
import { useEffect, useRef, useState } from "react";
const DIGIT_COUNT = 5;
const [value, setValue] = useState(new Array(DIGIT_COUNT).fill(""));
const refArr = useRef([]);Then, inside the component App, you define:
- DIGIT_COUNT – how many OTP input boxes you want
- value – state array to store each digit
- refArr – a mutable array to store refs for input boxes
✅ 2. Initial Focus Management
Use useEffect to focus the first input on component mount:
useEffect(() => {
refArr.current[0]?.focus();
}, []);✅ 3. Input Change Handling
Implementation logic for handling input changes:
const handleOnChange = (val, index) => {
val = val.trim();
const newArray = [...value];
newArray[index] = val.slice(-1); // Only last character
setValue(newArray);
val && refArr.current[index + 1]?.focus();
};This ensures only the last digit is used when pasting multiple characters
You define handleOnChange to:
- Accept only the last character typed
- Update the state for the current index
- Automatically focus the next input box if there is input
✅ 4. Backspace Handling
Implement backward navigation for better UX:
const handleOnKeyDown = (e, index) => {
if (!value[index] && e.key === "Backspace") {
refArr.current[index - 1]?.focus();
}
};This improves UX for deleting digits quickly.
You define handleOnKeyDown to handle backward navigation:
- If the current input is empty and the user presses Backspace, move focus to the previous input
✅ 5. Rendering the OTP Boxes
{value.map((val, index) => {
return (
<input
className="box"
key={index}
type="number"
value={value[index]}
onChange={(e) => handleOnChange(e.target.value, index)}
ref={(val) => (refArr.current[index] = val)}
onKeyDown={(e) => handleOnKeyDown(e, index)}
/>
);
})}You map over the value array and render an <input> for each digit:
- Assign ref so you can control focus
- Limit input to one number
- Call the respective handlers for onChange and onKeyDown
✅ 6. Styling (Assumed from styles.css)
Each input is styled with the .box class to look uniform and user-friendly. A typical CSS for OTP boxes might look like:
.box {
width: 40px;
height: 40px;
font-size: 24px;
text-align: center;
margin: 0 5px;
}✅ 7. Resulting Behavior
The final OTP input component:
- Renders 5 separate input boxes
- Focuses the first input on load
- Automatically moves focus as you type or backspace
- Accepts only 1 digit per box
- Provides a smooth user experience like most OTP inputs on modern apps
Key Features
- Automatic focus progression
- Single character validation
- Backspace navigation
- Paste handling