Geliştirme ortamında useEffect neden iki kez çalışıyor? Bu bir hata mı?

Cevap

Hata değil. React 18+ ile <StrictMode> açıkken, sadece development ortamında React her bileşeni mount ettikten hemen sonra efektleri bir kez temizleyip (cleanup) tekrar çalıştırır: mount -> unmount -> mount. Amaç, cleanup'ı eksik olan efektleri erkenden yakalamaktır. Production'da efekt bir kez çalışır.

Neden böyle?

Gelecekteki özellikler (ör. <Activity> ile ekran dışına alınan bileşenlerin state'i korunarak geri getirilmesi, Fast Refresh) bileşenlerin birden fazla kez mount/unmount olabilmesini gerektirir. Efektiniz buna dayanıklı değilse StrictMode bunu görünür kılar.

Doğru yaklaşım: düzgün cleanup yazmak

useEffect(() => {
  const controller = new AbortController();
  fetch(`/api/users/${id}`, { signal: controller.signal })
    .then((r) => r.json())
    .then(setUser)
    .catch((e) => { if (e.name !== "AbortError") setError(e); });
  return () => controller.abort();
}, [id]);

useEffect(() => {
  const conn = createConnection(roomId);
  conn.connect();
  return () => conn.disconnect();
}, [roomId]);

Yanlış çözümler

  • StrictMode'u kaldırmak: sorunu gizler.
  • useRef ile "zaten çalıştı" bayrağı tutmak: genelde asıl sorunu (eksik cleanup) çözmez.

İstisna

Analytics "sayfa görüntülendi" gibi gerçekten bir kez olması gereken işlemler dev'de iki kez görünür; bu kabul edilebilir. Satın alma gibi kullanıcı aksiyonları zaten efektte değil event handler'da olmalıdır.

  1. Virtual DOM nedir ve reconciliation nasıl çalışır?KolayReactFrontend
  2. Listelerde key prop neden önemlidir? Index kullanmak neden sorunludur?KolayReactFrontend
  3. Controlled ve uncontrolled component farkı nedir?KolayReactFrontend
  4. useEffect bağımlılık dizisi nasıl çalışır?OrtaReactFrontend
  5. useMemo ile useCallback arasındaki fark nedir?OrtaReactFrontend
  6. Gereksiz render'ları nasıl tespit eder ve önlersiniz?ZorReactFrontend

Bu konuda başka bir soru biliyor musun?

Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.

Soru ekle