3秒でわかる
ブラウザが自動で行う動作を止めるメソッド。フォーム送信での画面遷移やリンク移動を抑え、JavaScript 側で処理を引き取ります。
もう少し詳しく
どういうものか
event.preventDefault は、イベントに対してブラウザがあらかじめ持っている既定の動作を取り消すメソッドです。フォームの submit なら送信と画面の再読み込み、リンクの click なら別ページへの移動、チェックボックスの click なら選択状態の切り替えが既定の動作にあたります。
呼び出しても、イベントが親へ伝わること自体は止まりません。伝播を止めるのは別のメソッドです。
なぜ必要か
入力内容を JavaScript で検証してから送りたい、あるいは画面遷移せずに fetch で送信したい、という場面では、既定の動作が先に走ってしまうと処理が続きません。preventDefault を最初に呼ぶことで、そのイベントの主導権をコードの側に移せます。
具体例
フォームを非同期で送る典型的な形です。
const form = document.querySelector("#contact");
form.addEventListener("submit", async (event) => {
event.preventDefault(); // 画面遷移を止める
const data = new FormData(form);
const res = await fetch("/api/contact", { method: "POST", body: data });
document.querySelector("#msg").textContent = res.ok ? "送信しました" : "失敗しました";
});React でも考え方は同じです。
function SearchBox({ onSearch }) {
const [q, setQ] = useState("");
return (
<form onSubmit={(e) => { e.preventDefault(); onSearch(q); }}>
<input value={q} onChange={(e) => setQ(e.target.value)} />
</form>
);
}つまずきやすいところ
イベントの登録先を間違え、submit ではなくボタンの click に書いてしまう例が多く見られます。この場合、Enter キーでの送信は止まりません。フォームの送信を止めるなら、form 要素の submit で受けます。
非同期処理のあとに呼ぶのも効きません。await を挟んだ先で preventDefault を呼んでも、その頃には既定の動作が始まっています。ハンドラの先頭で呼ぶのが鉄則です。
スクロールに関わるイベントでは、passive が既定で真になっている場合があり、preventDefault が無視されて警告が出ます。止める必要があるなら { passive: false } を明示して登録します。
return false で代用しようとするのもつまずきの元です。古い属性での登録なら効きますが、addEventListener で登録したハンドラでは何も起きません。
似た用語との違い
| メソッド | 止めるもの |
|---|---|
| preventDefault | ブラウザの既定動作 |
| stopPropagation | 親要素へのイベント伝播 |
| stopImmediatePropagation | 伝播と、同じ要素の残りのハンドラ |
送信は止まったのに親のハンドラも動いてしまう、という症状は、必要なのが preventDefault ではなく stopPropagation だった、という取り違えです。