Cara mencegah double click tombol JavaScript yang paling aman adalah mengunci tombol selama proses berjalan. Pasang btn.disabled = true di baris pertama handler, kirim fetch, lalu buka lagi di finally. Tanpa kunci ini, klik kedua tetap membuat request kedua.
Kenapa Tombol Bisa Terkirim Dua Kali
Submit ganda hampir selalu soal timing, bukan browser rusak. Request butuh 1-3 detik, user mengira klik pertama gagal.
- Klik ganda saat request lambat dan user tidak sabar menekan lagi.
- Event click terpasang dua kali pada tombol yang sama karena script dimuat ulang.
- Tombol tidak dikunci selama proses fetch berjalan sehingga handler jalan paralel.
Pola Disable Tombol selama Proses Berjalan
Nonaktifkan tombol di awal handler, lalu aktifkan lagi di finally agar tidak terkunci permanen saat error.
const btn = document.querySelector("#btnKirim");
btn.addEventListener("click", async () => {
btn.disabled = true;
btn.textContent = "Mengirim...";
try {
const res = await fetch("/api/order", { method: "POST" });
if (!res.ok) throw new Error("Gagal: " + res.status);
} catch (err) {
console.error(err);
} finally {
btn.disabled = false;
btn.textContent = "Kirim";
}
});
Kode di atas memakai textContent karena hanya mengganti teks. Jangan pakai innerHTML untuk status tombol.
Perbandingan Metode Pencegah Klik Ganda
| Metode | Cocok Untuk | Catatan |
|---|---|---|
| disabled | Form dan submit | Memberi sinyal visual, didukung keyboard |
| flag isProcessing | Tombol custom non-form | Cek flag di awal handler sebelum fetch |
| debounce | Pencarian dan filter | Menunda eksekusi, bukan untuk submit |
| once | Aksi sekali pakai | Listener hapus otomatis setelah klik pertama |
Langkah Mencegah Double Submit pada Form
- Pasang listener pada tombol atau event submit form.
- Kunci tombol dengan disabled = true sebelum validasi berat.
- Kirim data memakai fetch dengan await.
- Cek response.ok dan tangani error tanpa membiarkan tombol terkunci.
- Kembalikan status tombol di blok finally.
FAQ
Apakah cukup memakai disabled saja?
Cukup untuk kebanyakan form, asal dibuka lagi di finally.
Kapan memakai debounce untuk tombol?
Pakai debounce untuk input pencarian, bukan untuk submit transaksi.
Kenapa tombol tetap bisa diklik dua kali?
Umumnya handler dipasang ganda atau tombol baru aktif sebelum request selesai.