🐣

react-hook-formで投稿したら再度フォーカスするフォームを作る

2022/06/15に公開

チャット的なUIでreact-hook-formを利用する際、submitしたらもう一度inputフォームにフォーカスするようなのをやりたくなった。

capture

出来上がったコード

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])

こちらはちょっと泥臭いのであまり使うケースは無さそうだ。

GitHubで編集を提案

Discussion