🙄

formState.isSubmittingがレンダリングしない

2024/04/19に公開

react-hook-formのformState.isSubmittingを使ってフォーム送信中にフォームを操作するUI(ボタン等)をdisabledにしたかったのだが、disabledになっていないように見えた。

結論

  • formStateをちゃんとsubscribeしてる?
  • submitが早すぎて見えてないだけじゃない?

コード

export default Page = () => {
	const { handleSubmit, formState: {isSubmitting} } = useFormContext()
	const onSubmit = () => {
		console.log("submit")
	}
	return (
		<form onSubmit={handleSubmit(onSubmit)} >
			{/* form field */}
			<button type="submit" disabled={isSubmitting}>submit</button>
		</form>
	)
}

これだとsubmitが早すぎて観測できないことがあるので、

const onSubmit = data => {
    return new Promise((resolve) => {
      setTimeout(() => resolve(), 1000);
    });
  };

これでも観測できない場合は、formStateオブジェクトを丸ごと呼び出しているかを確認する。

formStateはproxyでラップされている

無駄なレンダリングを防ぐためにformStateはプロキシでラップされている

= formStateはオブジェクトごとバッチで更新される

https://react-hook-form.com/docs/useform/formstate

つまり、formStateの変更を反映したい場合はformState全体をサブスクライブする必要がある

useEffect(() => {
  if (formState.errors.firstName) {
    // do the your logic here
  }
}, [formState]); // ✅ 
// ❌ formState.errors will not trigger the useEffect
// ❌ formState.isValid is accessed conditionally, 
// so the Proxy does not subscribe to changes of that state
return <button disabled={!formState.isDirty || !formState.isValid} />;
  
// ✅ read all formState values to subscribe to changes
const { isDirty, isValid } = formState;
return <button disabled={!isDirty || !isValid} />;

参考

https://github.com/react-hook-form/react-hook-form/issues/1363

Discussion