Introducing PrimeReact v11-alpha 🎉Discover Now

useInputOtp

Hook that manages OTP input state, focus navigation, and keyboard handling.

basic-demo

Usage#

import { useInputOtp } from '@primereact/headless/inputotp';
const { rootProps, getTextProps } = useInputOtp();
 
<div {...rootProps}>
    <input {...getTextProps(0)} />
    <input {...getTextProps(1)} />
    <input {...getTextProps(2)} />
    <input {...getTextProps(3)} />
</div>;

useInputOtp manages OTP value state, per-input focus navigation, and keyboard/paste handling. See Primitive for a component-based API.

Features#

  • Per-slot prop getter — getTextProps(index) returns the props for each OTP slot, including refs and handlers
  • Auto focus flow — advances focus on input, retreats on backspace, and supports left/right arrow navigation
  • Paste distribution — spreads clipboard content across the remaining slots in a single operation
  • Masking and numeric modes — mask switches to type="password", integerOnly restricts to digits with inputMode="numeric"
  • Controlled or uncontrolled — value driven via value/onValueChange or tracked internally from defaultValue

Working with callbacks#

Controlled value#

Pass value and onValueChange when the OTP should live in outside state — for form integration or async verification.

const [code, setCode] = React.useState('');
 
useInputOtp({
    value: code,
    onValueChange: (e) => setCode(e.value)
});

Numeric-only codes#

Enable integerOnly to restrict input to digits and signal numeric keyboards on mobile.

useInputOtp({ integerOnly: true });

Masked entry#

Set mask to render each slot as a password field — useful for sensitive tokens.

useInputOtp({ mask: true });

Auto-submit on completion#

Combine controlled value with a length check to trigger submission once all slots are filled.

const [code, setCode] = React.useState('');
 
useInputOtp({
    value: code,
    onValueChange: (e) => {
        setCode(e.value);
        if (e.value.length === 6) verify(e.value);
    }
});

Styling with data attributes#

The root element includes data-scope="inputotp" and data-part="root". Each input includes data-scope="inputotp" and data-part="input".

[data-scope='inputotp'][data-part='root'] {
    display: flex;
    gap: 0.5rem;
}
 
[data-scope='inputotp'][data-part='input'] {
    width: 2.5rem;
    text-align: center;
}
 
[data-scope='inputotp'][data-part='input']:focus {
    border-color: var(--p-primary-color);
}

API#

useInputOtp#

NameTypeDefault
valuestring—
Specifies whether a inputotp should be checked or not.
defaultValuestring—
Specifies whether a inputotp should be checked or not.
integerOnlybooleanfalse
When present, it specifies that only integers are allowed.
maskbooleanfalse
Mask pattern.
disabledbooleanundefined
When present, it specifies that the component should be disabled.
onValueChange(event: useInputOtpValueChangeEvent) => void—
Callback to invoke when value changes.

Accessibility#

Arrow keys move between slots, Backspace clears the current slot and moves left, and paste distributes characters across all slots. See Primitive for full WAI-ARIA compliance details.