useEffect, fonksiyonel bileşenlerde yan etkileri gerçekleştirmenizi sağlayan bir React hook'udur ve sınıf bileşenlerinin yaşam döngüsü yöntemlerini (componentDidMount, componentDidUpdate ve componentWillUnmount) değiştirir. React Documentation (2025)'a göre useEffect, React DOM'da değişiklikleri commit ettikten sonra çalışır ve gerçek DOM ağacına erişim sağlar. Hook, bir efekt işlevi ve yürütme sıklığını kontrol eden isteğe bağlı bir bağımlılık dizisi alır.
Önemli Noktalar
useEffect, React 16.8'de fonksiyonel bileşenlerde yan etkileri gerçekleştirmek için eklenmiş bir hook'tur. Yan etkiler, UI render'ı ile doğrudan ilgili olmayan işlemlerdir: API'lere HTTP istekleri, etkinlik abonelikleri, zamanlayıcılarla çalışma, DOM manipülasyonları, günlüğe kaydetme ve üçüncü taraf kütüphanelerle entegrasyon.
Hook'lardan önce, tüm bu işlemler sınıf bileşenlerinin yaşam döngüsü yöntemlerine yerleştirilmek zorundaydı: başlatma için componentDidMount, prop değişikliklerine tepki için componentDidUpdate, temizlik için componentWillUnmount. useEffect, bağımlılık dizisinin efektin ne zaman çalışması gerektiğini belirlediği tek bir API'de üç senaryoyu birleştirdi. Bu, mantığı basitleştirdi ve özellikle abonelik senaryolarında kod tekrarını azalttı.
React DevTools Usage Survey (2024)'e göre useEffect, useState'ten sonra en popüler ikinci hook'tur ve React uygulamalarının %89'unda kullanılır. Çoğu geliştirici onu veri getirme, harici sistemlerle senkronizasyon ve DOM etkinlik aboneliklerini yönetme için kullanır.
import { useEffect } from 'react';
function UserProfile({ userId }) {
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => setUser(data));
}, [userId]);
}
useEffect, React render'ı tamamlayıp DOM'u güncelledikten sonra iletilen efekt işlevini çalıştırır. Bu, render zamanı hesaplamalarından önemli bir farktır: efekt render'ı engellemez, bu da UX performansı için kritiktir. Efektler senkronize olarak çalışsaydı, kullanıcılar veri yüklenirken donmuş bir arayüz görürdü.
Tipik bir efektin yaşam döngüsü üç aşamadan oluşur. Bileşen montajında React efekti çalıştırır. Her güncellemede, dizideki en az bir bağımlılık değiştiyse, React önce önceki efektin temizleme işlevini, ardından yeni efekti çalıştırır. Bileşen demonte edildiğinde, yalnızca temizleme işlevi çalışır.
React Team — useEffect RFC (2024)'e göre useEffect'in dahili uygulaması, fiber ağacında bir yan etki kuyruğu kullanır. Değişiklikleri commit ettikten sonra (commit aşaması), React bu kuyruğu dolaşır ve efekt işlevlerini bileşende bildirildikleri sırayla çağırır. Her fiber düğümü, doğru temizlik ve yeniden çalıştırma için önceki efekte bir referans saklar.
| Aşama | React Eylemi | Ne Zaman Çalışır |
|---|---|---|
| Montaj | Efekt işlevini çağır | İlk render'dan sonra |
| Güncelleme | temizlik → efekt | Bağımlılıklar değiştiğinde |
| Demonte | Sadece temizlik | Bileşen kaldırıldığında |
Bağımlılık dizisi — useEffect'in ikinci argümanı — efektin ne zaman yeniden çalışması gerektiğini belirler. React, Object.is kullanarak dizideki her değeri önceki render ile karşılaştırır. En az bir değer değiştiyse, efekt yeniden çalışır. Dizi boşsa ([]), efekt montajdan sonra yalnızca bir kez çalışır.
Doğru bağımlılıkları seçmek, useEffect ile çalışmanın en zor kısmıdır. Dizi, efekt içinde kullanılan ve render'lar arasında değişebilen tüm değişkenleri ve işlevleri içermelidir. Bir bağımlılığı atlamak, eski kapanmalara (stale closures) yol açar — efekt önceki render'dan güncel olmayan bir değer görür. Gereksiz bağımlılıkları dahil etmek aşırı yeniden çalıştırmaya ve potansiyel hatalara neden olur.
// Bağımlılıklar, efektin ne zaman yeniden çalışacağını kontrol eder
useEffect(() => {
document.title = `User: ${user.name}`;
}, [user.name]); // yalnızca user.name değiştiğinde yeniden çalıştır
// eslint-disable-next-line react-hooks/exhaustive-deps
// Bir bağımlılığı atlarsanız, güncel olmayan veri alırsınız
React, eslint-plugin-react-hooks'u exhaustive-deps kuralıyla sağlar ve bu kural, bağımlılık dizisinin eksiksizliğini otomatik olarak kontrol eder. Meta Engineering Blog (2024)'e göre bu eklentiyi etkinleştirmek, hook ile ilgili hataları %72 oranında azaltır. Özel mantık içeren nadir durumlar dışında, tüm exhaustive-deps uyarılarını bir yorumla bastırmak yerine düzeltmeniz önerilir.
Bağımlılık dizisini hiç iletmezseniz, useEffect her render'dan sonra çalışır. Bu, DOM senkronizasyonu veya günlüğe kaydetme için yararlı olabilir, ancak çoğu zaman bir hatadır: efekt çok sık çalışır ve performans kaybına yol açar. Çoğu durumda, boş bir dizi (montajda bir kez) veya belirli props/state içeren bir dizi iletmelisiniz.
Boş dizi ([]), efektin hiçbir değere bağlı olmadığı ve kesin olarak bir kez çalıştığı anlamına gelir. Bu, sınıf bileşenlerinde componentDidMount'a eşdeğerdir. Ancak şunu unutmayın: efekt, bağımlılık dizisinde listelenmeyen props veya state kullanıyorsa, efekt bunların başlangıç değerlerini kullanır ve güncellemeleri asla görmez. Buna stale capture denir ve genellikle bulunması zor hataların kaynağıdır.
| Bağımlılık Dizisi | Davranış | Sınıf Eşdeğeri |
|---|---|---|
| Argüman yok | Her render'dan sonra | componentDidUpdate |
| [] | Montajda bir kez | componentDidMount |
| [a, b] | a veya b değiştiğinde | ComponentWillReceiveProps benzeri |
| return cleanup | Demonte etmeyi yönet | componentWillUnmount |
Temizleme işlevi, useEffect'in geri çağrısından döndürebileceği bir işlevdir. React, bileşen demonte edildiğinde ve bağımlılıklar değiştiğinde efekti yeniden çalıştırmadan önce onu çağırır. Temizlik, abonelikleri, zamanlayıcıları, istekleri ve serbest bırakılması gereken kaynakları iptal etmek için gereklidir.
Tipik bir örnek, WebSocket aboneliğidir. Montajda bir bağlantı oluşturulur; bağımlılık güncellemesinde yeniden oluşturulur (temizlik eskisini kapatır, efekt yenisini açar); demonte edildiğinde kapatılır. Temizlik olmadan, bileşenin her yeniden montajı yeni bir WebSocket bağlantısı oluşturur ve bu da bellek sızıntılarına ve birden çok bağlantıya yol açar.
useEffect(() => {
const socket = new WebSocket('wss://api.example.com');
socket.onmessage = event => setData(event.data);
// Temizleme işlevi — demonte etme sırasında ve yeniden çalıştırmadan önce çalışır
return () => {
socket.close();
};
}, []);
React Documentation (2025)'e göre AbortController, temizlikte fetch isteklerini iptal etmek için modern yaklaşımdır. Efekt bir HTTP isteği yaparsa ve bileşen tamamlanmadan demonte edilirse, istek çalışmaya devam eder ve demonte sonrası setState bir hataya neden olur. Efektin içinde bir AbortController oluşturun ve isteği iptal etmek için temizlikte controller.abort()'u çağırın.
En yaygın hata bağımlılıkları atlamaktır. Örneğin, efekt userId prop'unu kullanır, ancak bağımlılık dizisi boştur. Sonuç olarak, efekt ilk userId değeriyle bir kez çalışır ve değişikliklerine asla tepki vermez. Geliştirici, bileşenin yeni bir userId aldığını görür ancak veriler güncellenmez. exhaustive-deps kuralına sahip eslint-plugin-react-hooks bu tür hataları otomatik olarak algılar.
// ❌ Race condition — iptal yok
useEffect(() => {
fetch(`/api/user/${userId}`).then(res => setUser(res));
}, [userId]);
// ✅ AbortController ile düzeltildi
useEffect(() => {
const controller = new AbortController();
fetch(`/api/user/${userId}`, { signal: controller.signal })
.then(res => setUser(res));
return () => controller.abort();
}, [userId]);
Sonsuz döngü sorununu çözmek için, önceki state'e dayalı olarak state'i güncelleyen mantığı useEffect'e koymaktan kaçının. setState'in işlevsel formunu kullanın veya hesaplamaları efekt dışına taşıyın. Efekt, depolama veya tarayıcı etkinliklerine abone oluyorsa, dinleyici örneğinin her render'da değil, bir kez oluşturulduğundan emin olun.
Sıkça Sorulan Sorular
Doğrudan — hayır, çünkü useEffect senkron bir işlev veya undefined döndürülmesini bekler. Geri çağrı async olarak bildirilirse, React'in yok saydığı bir Promise döndürür ve temizleme mekanizması çalışmayı durdurur. Çözüm: efekt içinde bir async işlevi çağırın: useEffect(() => { async function load() { ... }; load(); }, []).
Sınır yoktur. React, aynı bağımlılık dizisine sahip olsalar bile ilgisiz mantığı ayrı useEffect'lere ayırmayı önerir. Her efekt, açıkça tanımlanmış bir yan görevden sorumlu olmalıdır: biri abonelikler için, diğeri veri yükleme için, üçüncüsü sekme başlığını senkronize etme için. Bu, anlamayı ve hata ayıklamayı basitleştirir.
React Strict Mode'da (yalnızca geliştirme modu), tüm efektler monte edilir, demonte edilir ve yeniden monte edilir. Bu bir özelliktir, hata değildir — React, temizliğin doğru çalışıp çalışmadığını kontrol eder. Demonte etme ve yeniden monte etmeden sonra efekt yanlış davranırsa (örneğin, yinelenen abonelikler), temizliğiniz eksiktir. Üretimde efekt bir kez çalışır.
AbortController kullanın. Efektin içinde bir controller oluşturun, controller.signal'ı fetch'e iletin ve temizlikte controller.abort()'u çağırın. İstek tamamlanmadan bileşen demonte edilirse, fetch iptal edilir ve setState çağrılmaz. Bu, yarış durumlarını ve “Can't perform a React state update on an unmounted component” hatasını önler.
useEffect istisnasız her render'dan sonra çalışır. Bu, efekt içindeki herhangi bir setState'in yeni bir render → yeni efekt → sonsuz döngüye neden olacağı anlamına gelir. Pratikte, bağımlılık dizisi olmayan bir efekt neredeyse her zaman bir hatadır. İstisnalar, her render'ın senkronizasyon gerektirdiği günlüğe kaydetme veya harici bir sistemle senkronizasyondur.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun