🐣
react-hook-formで投稿したら再度フォーカスするフォームを作る
チャット的なUIでreact-hook-formを利用する際、submitしたらもう一度inputフォームにフォーカスするようなのをやりたくなった。
出来上がったコード
export const RefocusInput: FC<{
onSubmit: (value: string) => void
}> = ({ onSubmit }) => {
const { register, handleSubmit, formState, setFocus, resetField } = useForm<{ value: string }>()
useEffect(() => {
setFocus("value")
}, [formState.submitCount])
return <form onSubmit={handleSubmit(async (data) => {
await onSubmit(data.value)
resetField("value")
})}>
<div>
<input
disabled={formState.isSubmitting}
{...register("value")} />
<button
disabled={formState.isSubmitting}
type="submit"
aria-label={"submit"} >
submit
</button>
</div>
</form>
}
やってること
送信部分
まず送信部分でresetField
することで入力を消している。本当は成功を確認してからのほうが良いかもしれない
<form onSubmit={handleSubmit(async (data) => {
await onSubmit(data.value)
resetField("value")
})}>
ちなみに、ここでsetFocus
すれば良いのでは?と思うところだが、どうやらこれは動かないらしかった
// ダメだった例
<form onSubmit={handleSubmit(async (data) => {
await onSubmit(data.value)
resetField("value")
setFocus("value")
})}>
### フォーカス部分
submitタイミングでフォーカスできないため、effectとしてフォーカスする必要がある。
今回フォーカスする部分はformState.submitCount
で送信回数が変わる事を起点にしている。
useEffect(() => {
setFocus("value")
}, [formState.submitCount])
resetField
ではなくreset({value:""})
を利用した場合、formState.submitCount
は0->1->0と変更され、利用できないようだった。
別解として、useWatch
で値が消えたタイミングでフォーカスするという手法もあった。
useEffect(() => {
if (!watchValue) {
setFocus("value")
}
}, [watchValue])
こちらはちょっと泥臭いのであまり使うケースは無さそうだ。
Discussion