Facebook Pixel

OTP Input Common Bugs and Fixes

Common bugs in OTP input implementations and how to fix each one.

OTP Input Common Bugs and Fixes

Here are common bugs in OTP input implementations and how to fix each one.

Bug 1: Backspace Does Not Go to Previous

Cause: only checking e.key === "Backspace" without checking if the current input is empty.

Fix: check !e.target.value before focusing the previous:

if (e.key === "Backspace" && !e.target.value && index > 0) { inputs[index - 1].focus(); } `` ### Bug 2: Paste Fills Only the First Input **Cause**: not calling `e.preventDefault()`, so the browser does the default paste. **Fix**: call `e.preventDefault()` and manually distribute the pasted text: ```js e.preventDefault(); const pasted = e.clipboardData.getData("text").replace(/\D/g, ""); `` ### Bug 3: Non-Numeric Characters Accepted **Cause**: no filtering on input. **Fix**: filter on every input event: ```js e.target.value = e.target.value.replace(/\D/g, ""); `` ### Bug 4: Focus Goes Beyond the Last Input **Cause**: not checking `index < inputs.length - 1` before focusing next. **Fix**: add the boundary check: ```js if (value && index < inputs.length - 1) { inputs[index + 1].focus(); } `` ### Bug 5: Verify Button Never Enables **Cause**: not calling `checkComplete()` after every input change. **Fix**: call `checkComplete()` at the end of every input handler: ```js input.addEventListener("input", (e) => { // ... handle input ... checkComplete(); }); `` ### Bug 6: Arrow Keys Do Not Work **Cause**: listening on `keydown` instead of `keyup`, or not handling ArrowLeft/ArrowRight. **Fix**: add a `keyup` listener for arrow keys: ```js input.addEventListener("keyup", (e) => { if (e.key === "ArrowLeft" && index > 0) inputs[index - 1].focus(); if (e.key === "ArrowRight" && index < inputs.length - 1) inputs[index + 1].focus(); }); `` ### The Takeaway Common OTP bugs: backspace not going to previous (check empty), paste filling only first (preventDefault), non-numeric accepted (regex filter), focus beyond last (boundary check), verify never enables (call checkComplete), and arrow keys not working (keyup listener). Fix each with the appropriate check or handler.

Because you are not checking if the current input is empty before focusing the previous. The fix: if (e.key === 'Backspace' && !e.target.value && index > 0) inputs[index - 1].focus(). Only go back when the current input is already empty.

Because you are not calling e.preventDefault(). The browser does the default paste, which fills only the current input (and truncates to maxlength=1). Call e.preventDefault() and manually distribute the pasted text across the inputs.

Because you are not filtering non-numeric characters. Add e.target.value = e.target.value.replace(/\D/g, '') on the input event. This removes all non-digit characters.

Because you are not calling the completion check after every input change. Add checkComplete() at the end of every input handler. The function should check if all inputs have a value and enable/disable the button.

Add a boundary check before focusing the next input: if (value && index < inputs.length - 1) inputs[index + 1].focus(). The condition index < inputs.length - 1 prevents focusing beyond the last input.

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.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.