formの挙動で詰まった件
ものすごーく初歩的なミス(理解不足)で時間を消費してしまったので、戒めを込めてメモします。
起こったこと
Next.jsで作成したアプリケーションで、ライブラリ等を使用せずに検索フォームを作成していた。
具体的には以下のような、<form>
を実装して、Enterを押下すると検索処理が走るような実装を行なっていた。
const handleSearch = () => {
console.log("searchForm", searchForm);
router.push({ pathname: "/posts/search", query: { q: searchForm } });
}
return (
<div className={styles.content}>
<h3>検索</h3>
<form onSubmit={handleSearch} className={styles.searchForm}>
<input
type="text"
placeholder="キーワードを入力"
aria-label="キーワードを入力"
onChange={(e) => setSearchForm(e.target.value)}
/>
</form>
</div>
)
検索結果をクエリパラメータをもとにSSRで取得するページに遷移するためにrouter.pushを実装。
この実装で何が困ったかというと、router.push で遷移した先が表示されると、1, 2秒後に勝手にリダイレクトが走り元のページに戻って(ま遷移して)しまうという挙動になった。
原因
すごく初歩的なミスで、 <form> の動作を全然理解できていなかったせい。
<form> の送信時には、デフォルトで <form action=”〇〇”>で指定しているURLへリダイレクトがかかる。
action
属性は、どこにデータを送信するかを定義します。値は妥当な相対/絶対 URL でなければなりません。この属性が与えられなかった場合は、フォームが含まれているページの URL にデータが送信されます。
実行順序としては、以下のような形になっていた模様(自分では調べてはいない)
おそらくonSubmitでrouter.pushが動く関数を設定していたものの、その後フォームが送信されているURLへのデータの送信が発生し、action実行元へまた戻ってしまうような挙動となってしまっていたみたい。
解決方法
<form action=””>
によるリダイレクトを発生させないためには、e.preventDefault()
によってformのデフォルトの動きを止めてやる必要がある。
preventDefault()
はEvent
インターフェイスのメソッドで、ユーザーエージェントに、このイベントが明示的に処理されない場合に、その既定のアクションを通常どおりに行うべきではないことを伝えます。
なぜこうなったのか
react-hook-formを愛用していたということが大きかもしれない。
普段からonSubmitに実行する関数をセットしている上に、preventDefaultを実行しなくても挙動をキャンセルしてくれていたことで、formの基本的な挙動がすっかり頭から抜け落ちてしまっていた模様…………。
<form onSubmit={handleSubmit(onSubmit)}>
<label htmlFor=''>First Name</label>
<input type='text' {...register('firstName')} />
<label htmlFor=''>Gender Selection</label>
<select {...register('gender')}>
<option value='female'>female</option>
<option value='male'>male</option>
<option value='other'>other</option>
</select>
<input type='submit' />
</form>
便利なライブラリに頼るのもいいですが、基本はしっかり頭に入れた上で使用することが大切ですね……。
参考
記事内以外のその他参考記事