🐣
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