- Konu sahibi
- #1
React formunda gönderim ve bekleme durumunu yönetmek için formun
Form gönderildiğinde aşağıdaki durum geçişi uygulanır:
Bekleme göstergesi yalnızca görsel bir metin olmamalıdır. Düğmenin
Aşağıdaki bileşen harici bir sunucuya bağlanmaz;
Çalıştırıldığında normal bir e-posta ile gönderim düğmesi yaklaşık 1,2 saniye devre dışı kalır ve başarı mesajı görünür.
Aynı anda hem
Tablodaki
Bu parça success alanı döndüren varsayımsal JSON sözleşmesi içindir; kendi API yanıtınıza uyarlayın. Alanları devre dışı bırakmadan önce FormData okunmuştur; devre dışı kontroller normal form verisine eklenmez. Sunucu doğrulama hatası döndürürse bunu genel bir “bir şeyler ters gitti” mesajıyla gizlemek yerine ilgili alana veya forma anlaşılır biçimde yansıtın. İstemci tarafındaki
Gönderim işleyicisinin ilk satırlarında
Kullanıcıya bekleme mesajını göstermeye devam edin; uygulamanızda kabul edilebilir bir süre sınırı varsa
onSubmit olayında varsayılan tarayıcı davranışını durdurun, isteğin başladığı anda bir pending durumu ayarlayın ve istek bitince başarı ya da hata durumuna geçin. Gönderim düğmesini bekleme sırasında devre dışı bırakmak tekrarlı kullanıcı girişini azaltır. Yenileme, başka sekme veya ağ yeniden denemesinde aynı kaydın iki kez oluşmamasını ise sunucudaki idempotency/tutarlılık kuralı sağlamalıdır.Temel çalışma mantığı
Form gönderildiğinde aşağıdaki durum geçişi uygulanır:
-
event.preventDefault()ile sayfanın yenilenmesini engelleyin. - Form verisini okuyun ve temel doğrulamayı yapın.
- İstek başlamadan önce durumu
pendingyapın. - Asenkron isteği
trybloğunda çalıştırın. - Başarılı yanıtta başarı mesajı, hatada hata mesajı gösterin.
-
finallyiçinde bekleme durumunu sonlandırın veya başarı/hata durumuna geçin.
Bekleme göstergesi yalnızca görsel bir metin olmamalıdır. Düğmenin
disabled olması, formun beklemede olduğunu ekran okuyuculara bildiren aria-busy niteliği ve canlı durum mesajı birlikte daha anlaşılır bir arayüz sağlar.Çalıştırılabilir en küçük örnek
Aşağıdaki bileşen harici bir sunucuya bağlanmaz;
fakeRequest gerçek ağ isteğini temsil eden varsayımsal bir gecikmedir. Bileşeni bir React projesindeki ContactForm.jsx dosyasına koyup sayfada <ContactForm /> olarak kullanabilirsiniz.
JavaScript:
import { useRef, useState } from "react";
function fakeRequest(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (data.email === "[email protected]") {
reject(new Error("Sunucu isteği reddetti."));
return;
}
resolve({ ok: true });
}, 1200);
});
}
export default function ContactForm() {
const [status, setStatus] = useState("idle");
const [message, setMessage] = useState("");
const submitting = useRef(false);
async function handleSubmit(event) {
event.preventDefault();
if (submitting.current) return;
const form = event.currentTarget;
const data = new FormData(form);
const name = String(data.get("name") || "").trim();
const email = String(data.get("email") || "").trim();
if (!name || !email) {
setStatus("error");
setMessage("Ad ve e-posta alanları zorunludur.");
return;
}
submitting.current = true;
setStatus("pending");
setMessage("Gönderiliyor...");
try {
await fakeRequest({ name, email });
form.reset();
setStatus("success");
setMessage("Form başarıyla gönderildi.");
} catch (error) {
setStatus("error");
setMessage(error instanceof Error ? error.message : "Gönderim sırasında bir hata oluştu.");
} finally {
submitting.current = false;
}
}
const isPending = status === "pending";
return (
<form onSubmit={handleSubmit} aria-busy={isPending}>
<label>
Ad
<input name="name" type="text" required disabled={isPending} />
</label>
<label>
E-posta
<input name="email" type="email" required disabled={isPending} />
</label>
<button type="submit" disabled={isPending}>
{isPending ? "Gönderiliyor..." : "Gönder"}
</button>
<p role="status" aria-live="polite">{message}</p>
</form>
);
}
Çalıştırıldığında normal bir e-posta ile gönderim düğmesi yaklaşık 1,2 saniye devre dışı kalır ve başarı mesajı görünür.
[email protected] girildiğinde hata yolu çalışır; bu adres yalnızca örneğin kontrollü olarak başarısız olmasını sağlar. Gerçek uygulamada fakeRequest yerine sunucunuzun API isteğini koymalısınız.Durumları seçerken pratik kararlar
Aynı anda hem
isLoading hem isSubmitting gibi birbirini tekrar eden değişkenler tutmak yerine formun ihtiyacına göre tek bir durum veya birkaç açık durum kullanın. Başarı mesajını yeni bir gönderim başladığında temizlemek, eski sonucun yeni isteğin sonucu sanılmasını önler.| Durum | Kullanıcıya gösterilecek davranış | Sonraki işlem |
|---|---|---|
| idle | Form normal şekilde düzenlenir. | Gönderim olayını bekle. |
| pending | Düğmeyi ve gerekirse alanları devre dışı bırak; bekleme mesajı göster. | İstek sonucunu bekle. |
| success | Başarı mesajı göster; gerekiyorsa formu temizle. | Yeni gönderime izin ver. |
| error | Hatanın anlaşılır açıklamasını göster; girilen verileri koru. | Kullanıcının düzeltip yeniden denemesine izin ver. |
Tablodaki
error durumunda formu otomatik olarak temizlememek önemlidir. Kullanıcı, başarısız bir isteğin ardından bütün alanları yeniden doldurmamalıdır. Başarıdan sonra temizleme kararı ise formun kullanımına bağlıdır; iletişim formunda uygun olabilir, taslak düzenleyicide veriyi korumak daha doğru olabilir.Gerçek API isteğine geçerken
fetch kullandığınızda yalnızca ağ hatasını yakalamak yeterli değildir. HTTP 400 veya 500 yanıtları çoğu durumda fetch tarafından otomatik olarak catch bloğuna gönderilmez. Bu nedenle yanıtı kendiniz kontrol edin:
JavaScript:
const response = await fetch("/api/contact", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, email })
});
const outcome = await response.json();
if (!response.ok || outcome.success !== true) {
throw new Error("Sunucu formu kabul etmedi.");
}
Bu parça success alanı döndüren varsayımsal JSON sözleşmesi içindir; kendi API yanıtınıza uyarlayın. Alanları devre dışı bırakmadan önce FormData okunmuştur; devre dışı kontroller normal form verisine eklenmez. Sunucu doğrulama hatası döndürürse bunu genel bir “bir şeyler ters gitti” mesajıyla gizlemek yerine ilgili alana veya forma anlaşılır biçimde yansıtın. İstemci tarafındaki
required kontrolü kullanıcı deneyimi içindir; güvenlik ve veri doğrulaması sunucuda da yapılmalıdır.Sık yapılan hatalar
- Bekleme durumunu ayarlamadan asenkron isteği başlatmak: Kullanıcı birden fazla kez tıklayabilir.
-
finallyveya eşdeğer sonlandırma mantığı olmadan hata almak: Form düğmesi sonsuza kadar devre dışı kalabilir. - Başarısız gönderimde
form.reset()çağırmak: Kullanıcının düzeltebileceği veriler kaybolur. -
onClickiçinde gönderim yapmak: Enter tuşuyla gönderim ve formun doğal erişilebilirlik davranışı atlanabilir; ana mantıkonSubmitiçinde olmalıdır. - Yalnızca düğme metnini değiştirmek: Bekleme durumunda düğme devre dışı bırakılmazsa çift gönderim yine mümkündür.
Kaynaklar
Sık sorulan sorular
Form gönderildiğinde sayfanın yenilenmesini nasıl önlerim?
Gönderim işleyicisinin ilk satırlarında
event.preventDefault() çağırmalısınız. Bu çağrı yoksa tarayıcı formu varsayılan yöntemiyle gönderip sayfayı yenileyebilir.İsteğin çok uzun sürmesi durumunda ne yapmalıyım?
Kullanıcıya bekleme mesajını göstermeye devam edin; uygulamanızda kabul edilebilir bir süre sınırı varsa
AbortController ile isteği iptal edip yeniden deneme seçeneği sunabilirsiniz. İsteğin tarayıcıda iptal edilmesi sunucunun işlemi geri aldığı anlamına gelmez. Sonuç belirsizse durum sorgulama ve aynı idempotency anahtarıyla güvenli yeniden deneme tasarlayın; doğrudan “hiç kayıt olmadı” varsaymayın.