OTP Input Component in React
Building the OTP input in React with hooks. Here is the implementation with state management.
OTP Input Component in React
Building the OTP input in React with hooks. Here is the implementation with state management.
Component
import React, { useState, useRef } from "react"; function OTPInput({ length = 4, onComplete }) { const [values, setValues] = useState(Array(length).fill("")); const inputsRef = useRef([]); const handleChange = (index, value) => { const digit = value.replace(/\D/g, ""); const newValues = [...values]; newValues[index] = digit; setValues(newValues); if (digit && index < length - 1) { inputsRef.current[index + 1].focus(); } if (newValues.every((v) => v) && onComplete) { onComplete(newValues.join("")); } }; const handleKeyDown = (index, e) => { if (e.key === "Backspace" && !values[index] && index > 0) { inputsRef.current[index - 1].focus(); } }; const handlePaste = (index, e) => { e.preventDefault(); const pasted = e.clipboardData.getData("text").replace(/\D/g, ""); const newValues = [...values]; pasted.split("").forEach((char, i) => { if (index + i < length) { newValues[index + i] = char; } }); setValues(newValues); const nextIndex = Math.min(index + pasted.length, length - 1); inputsRef.current[nextIndex].focus(); }; return ( <div className="otp-container" role="group" aria-label="Enter OTP"> {values.map((value, index) => ( <input key={index} ref={(el) => (inputsRef.current[index] = el)} type="text" maxLength={1} value={value} onChange={(e) => handleChange(index, e.target.value)} onKeyDown={(e) => handleKeyDown(index, e)} onPaste={(e) => handlePaste(index, e)} aria-label={`Digit ${index + 1}`} inputMode="numeric" className="otp-input" /> ))} </div> ); } `` ### Usage ```jsx function App() { const handleComplete = (otp) => { console.log("OTP:", otp); // verify with API }; return <OTPInput length={4} onComplete={handleComplete} />; } `` ### Features - State managed with `useState` (array of values). - Refs for focus management (`useRef`). - Auto-focus next on input. - Backspace to previous. - Paste support. - `onComplete` callback when all inputs are filled. - Accessible (aria-label, role). ### The Takeaway React OTP input: useState for values (array), useRef for input focus management, onChange for auto-focus, onKeyDown for backspace, onPaste for paste support, and onComplete callback. Accessible with aria-label. This is a reusable component that can be dropped into any React app.
Use useState for the values array (e.g., ['', '', '', '']). Use useRef for input references (for focus management). Handle onChange (auto-focus next), onKeyDown (backspace to previous), and onPaste (fill multiple). Call onComplete when all inputs are filled.
Use useRef to store references to each input: inputsRef.current[index]. To focus the next input: inputsRef.current[index + 1].focus(). To focus the previous: inputsRef.current[index - 1].focus().
Use useState with an array: const [values, setValues] = useState(Array(length).fill('')). On change, update the specific index: const newValues = [...values]; newValues[index] = digit; setValues(newValues).
Add onPaste handler. preventDefault, get the pasted text from e.clipboardData.getData('text'), filter to numeric, split into characters, and update the values array starting from the current index. Focus the last filled input.
After each change, check if all values are filled: if (newValues.every(v => v) && onComplete) onComplete(newValues.join('')). This calls the parent's callback with the full OTP string when all inputs are complete.
Ready to master React completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master React
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

