Back

OTP Verification Input

easy

Streak

0 days

Progress

0%

Submitted

0

OTP Verification Input

React30 mineasyFree

Prompt

Build a six-digit OTP verification input used in login, payment confirmation, and account recovery flows. It should feel fast for keyboard users and forgiving for paste flows.

Each box accepts one digit. Typing advances focus, Backspace moves backward when the current box is empty, arrow keys move between boxes, and pasting a full code distributes digits across boxes.

The important part is not visual styling; it is focus control, numeric sanitization, and keeping the code as a single derived value while rendering six inputs.

Requirements

  • →Render six single-character numeric inputs.
  • →Typing a digit moves focus to the next input.
  • →Backspace on an empty input moves focus to the previous input.
  • →Left and right arrow keys navigate between inputs.
  • →Pasting digits distributes them across remaining boxes.
  • →Include resend countdown and invalid-code feedback.
Example
Loading preview...
For the best coding experience, we recommend using a desktop device.
Preparing Sandbox...
Premium interview report

What interviewers score in this build

Use this before reading the code. It tells you what to say, what to test, and where machine-coding candidates usually lose points.

Interview signals

  • Controlled state: Uses one coherent digit array and derives the submitted code.
  • Focus handling: Moves focus forward and backward without trapping the user.
  • Paste support: Distributes pasted digits correctly from the current input.
  • Validation: Handles incomplete and invalid codes with clear feedback.

Time checkpoints

  1. 1

    0-5 min: Clarify requirements, success states, and edge cases.

  2. 2

    5-12 min: Model the state shape and derive the key data transformations.

  3. 3

    12-25 min: Build the main UI and happy-path interactions.

  4. 4

    25-38 min: Add validation, failure, and boundary behavior.

Edge-case checklist

Empty / initial state for OTP Verification Input
Keyboard and focus behavior
Rapid repeated interactions
Cleanup on unmount (timers/listeners/observers)

Common mistakes

  • Jumping to JSX before naming state and events
  • Derived values stored as redundant state
  • Missing disabled/loading/empty treatments
  • Skipping accessibility until the end
SolutionRead-only · Live Preview

Technical Explanation

How to Think About This Problem

An OTP component looks small, but it is a focus-management problem. The user expects it to behave like one input, even though the UI shows six boxes.

The senior approach is to keep one source of truth for the code, then make focus movement feel natural. The code is data. Focus is behavior.

State Model

Use an array of six strings:

const [digits, setDigits] = useState(Array(6).fill(''));
const code = digits.join('');

This is easier than six separate state variables. Paste, delete, validation, and reset all become simple array operations.

Refs for Focus

To move focus between boxes, store input nodes in an array ref:

const refs = useRef([]);
refs.current[index + 1]?.focus();
refs.current[index - 1]?.focus();

This is okay because focus is an imperative browser action. You are not using refs to hide state from React. You are using them to call the DOM focus API.

Key Behaviors

  • Typing: keep only the last numeric character and move to the next box.
  • Backspace: if the current box is empty, move to the previous box.
  • Arrow keys: move left and right without changing digits.
  • Paste: sanitize the pasted value and distribute digits from the current box.
  • Verify: validate the derived code, not each input separately.

Paste Handling

Paste is the edge case that separates a polished OTP input from a basic one. Users often copy the whole code from SMS or email. If they paste into the first box, all boxes should fill.

const pasted = text.replace(/\D/g, '').slice(0, 6 - index);
setDigits(current => {
  const next = [...current];
  pasted.split('').forEach((char, offset) => {
    next[index + offset] = char;
  });
  return next;
});
Common Pitfall: Treating each box as a separate form field

That makes the component harder than it needs to be. The product cares about one code, not six unrelated values.

Mobile Details

Use inputMode="numeric" so mobile devices show the numeric keyboard. Use autoComplete="one-time-code" on the first input so supported browsers can suggest SMS codes.

Edge Cases

  • Paste values with spaces or dashes, like 492-817.
  • Delete from the middle and continue typing.
  • Submit before all six digits are present.
  • Show invalid-code feedback and reset focus to the first box.
  • Disable resend until the timer finishes.
Interview Tip

Say: "I want the six boxes to behave like one logical input. The array stores the code, and refs only handle focus movement."

Remember: For OTP Verification Input: nail the state model before JSX — Controlled state, Focus handling, Paste support.

Say this in the interview: I would clarify interactions for OTP Verification Input, model state and derived UI first, then build components around that invariant.

Interview Criteria

Controlled state

Uses one coherent digit array and derives the submitted code.

Focus handling

Moves focus forward and backward without trapping the user.

Paste support

Distributes pasted digits correctly from the current input.

Validation

Handles incomplete and invalid codes with clear feedback.

Mobile ergonomics

Uses numeric input mode and one-time-code autocomplete.

Time Checkpoints

0-5 min

0-5 min: Clarify requirements, success states, and edge cases.

5-12 min

5-12 min: Model the state shape and derive the key data transformations.

12-25 min

12-25 min: Build the main UI and happy-path interactions.

25-38 min

25-38 min: Add validation, failure, and boundary behavior.

38-48 min

38-48 min: Add accessibility and responsive polish.

48-55 min

48-55 min: Manually test flows and explain trade-offs.

Streak

0 days

Last active: Sign in to track

Progress

0%

0/0 solved

Submitted

0

Solutions pushed to review history.