RHFで発生した「no-misused-promises」エラーの解決方法
はじめに
React でフォームを扱う際に react-hook-form
を使用していると、以下のようなコードを書きたくなることがあります。
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
しかし、このコードを ESLint によってチェックすると、以下のようなエラーが発生することがあります。
Promise-returning function provided to attribute where a void return was expected.
eslint[@typescript-eslint/no-misused-promises](https://typescript-eslint.io/rules/no-misused-promises)
このエラーがなぜ発生するのか、どのように解消すればよいのかを解説します。
エラー内容
エラーの内容を簡単に説明すると、onSubmit
に渡す関数がPromise
を返しているため、型の不一致が発生しているというものです。
Reactの<form>
のonSubmit
属性には、() => void
型の関数が求められています。しかし、form.handleSubmit(onSubmit)
はPromise<void>
を返すため、型の不一致が発生し、ESLintによって警告されます。
つまり、以下のコードが問題になっています。
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
form.handleSubmit(onSubmit)
はすぐに実行され、戻り値としてPromise<void>
を onSubmit
に渡してしまうため、ESLintの@typescript-eslint/no-misused-promises
ルールに違反してしまいます。
解消方法
このエラーを解消するには、無名関数でラップする 方法を取ります。
<form onSubmit={() => form.handleSubmit(onSubmit)} className="space-y-8">
このようにすることで、onSubmit
に渡されるのは() => void
型の関数となり、型の不一致が解消されます。
また、async
を使って以下のように書くこともできます。
<form
onSubmit={async (e) => {
e.preventDefault(); // 必要に応じてデフォルト動作を防ぐ
await form.handleSubmit(onSubmit)();
}}
className="space-y-8"
>
この方法ではawait
を使うことでform.handleSubmit(onSubmit)
の完了を待つことができ、エラーハンドリングも組み込みやすくなります。
どうして解消したのか
解消方法が機能する理由を簡単にまとめると、
-
エラーの原因:
form.handleSubmit(onSubmit)
がPromise<void>
を返すため、Reactが期待する() => void
の型と一致しない。 -
解決策:
() => form.handleSubmit(onSubmit)
のように無名関数を使うことで、Reactが期待する() => void
の型と一致させる。 -
追加の解決策:
async (e) => { e.preventDefault(); await form.handleSubmit(onSubmit)(); }
のように書くことで、より適切な非同期処理が可能になる。
まとめ
Reactの<form>
にreact-hook-form
を組み合わせる際、handleSubmit
をそのまま onSubmit
に渡すとPromise<void>
を返してしまい、ESLintの@typescript-eslint/no-misused-promises
ルールに違反することがあります。
この問題は、onSubmit={() => form.handleSubmit(onSubmit)}
のように無名関数でラップすることで解消できます。
また、非同期処理を適切に行いたい場合は、async (e) => { e.preventDefault(); await form.handleSubmit(onSubmit)(); }
のように書くことで、より安全なフォーム処理が可能になります。
ReactとTypeScriptを組み合わせる際には、このような細かい型の違いに気をつけながら開発を進めることが重要です!
Discussion