メインコンテンツまでスキップ

OTPInput

挙動

OTPInput

使用ライブラリ

ソースコード

ソースコード
'use client'

import { ChangeEvent, useRef, KeyboardEvent } from 'react'

const OtpInputPage: React.FC = () => {
const inputs = useRef<HTMLInputElement[]>([])

// 入力時の処理
const handleInputChange = (index: number) => (e: ChangeEvent<HTMLInputElement>) => {
let value = e.target.value

// 入力値が英数字かチェック
const isValid = /^[a-zA-Z0-9]$/.test(value)
if (!isValid) {
e.target.value = ''
return
}

// 大文字に変換
value = value.toUpperCase()
e.target.value = value

// 次の入力欄にフォーカス
if (value.length === 1 && index < inputs.current.length - 1) {
inputs.current[index + 1].focus()
}
}

// Backspaceキーが押された場合、前の入力欄にフォーカス
const handleKeyDown = (index: number) => (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Backspace' && index > 0) {
if (e.currentTarget.value.length === 0) {
inputs.current[index - 1].focus()
} else {
inputs.current[index].value = ''
}
} else if (e.key === 'ArrowLeft' && index > 0) {
inputs.current[index - 1].focus()
} else if (e.key === 'ArrowRight' && index < inputs.current.length - 1) {
inputs.current[index + 1].focus()
}
}

const assignRef = (index: number) => (el: HTMLInputElement | null) => {
if (!el) return
inputs.current[index] = el
}

return (
<div className='flex justify-center mt-10'>
{Array(6)
.fill(0)
.map((_, index) => (
<input
key={index}
type='text'
maxLength={1}
ref={assignRef(index)}
onChange={handleInputChange(index)}
onKeyDown={handleKeyDown(index)}
className='w-10 h-14 text-center m-1 text-2xl border border-gray-300 rounded-md'
/>
))}
</div>
)
}

export default OtpInputPage

検証ページ

こちら