- Konu sahibi
- #1
React
Bir bileşen güncellendiğinde genel akış şöyledir:
Effect'in tam olarak tarayıcının boyamasından önce veya sonra çalışacağına güvenilmemelidir. Kullanıcıya görünmeden önce layout ölçümü gibi bir iş yapılması gerekiyorsa
Aşağıdaki ayrım, effect'in ne zaman yeniden çalışacağını belirler:
React her bağımlılığı önceki değerle
Aşağıdaki örnekte effect ilk render sonrasında çalışır;
Bu bileşen başarıyla çalıştığında önce
Effect yalnızca istemci tarafında çalışır; sunucu tarafı render sırasında tarayıcıya özgü DOM veya ağ yan etkilerine güvenilmemelidir. Ayrıca effect'in içinden state değiştirmek yeni bir render başlatabileceğinden, bağımlılıkları değişen state'i yeniden yazan bir effect sonsuz döngü oluşturabilir.
useEffect, bileşenin render sonucu DOM'a uygulandıktan sonra çalışır. İlk render sonrasında bir kez, bağımlılık dizisindeki değerler değiştiğinde yeniden veya bağımlılık dizisi verilmezse her başarılı render sonrasında çalışabilir. Bu nedenle veri çekme, abonelik kurma, document başlığını değiştirme ve React dışındaki bir API ile senkronizasyon gibi yan etkiler için kullanılır; render sırasında çalışması gereken hesaplamalar için kullanılmaz.Çalışma sırası
Bir bileşen güncellendiğinde genel akış şöyledir:
- React bileşeni çalıştırır ve yeni JSX'i hesaplar.
- React değişiklikleri DOM'a uygular; buna commit aşaması denir.
- Effect'in bağımlılıkları kontrol edilir.
- Bağımlılık değiştiyse önce eski effect’in cleanup işlevi eski değerlerle çalışır. İlk kurulumda eski cleanup yoktur.
- Ardından yeni effect’in setup callback’i yeni değerlerle çalışır; unmount sırasında son cleanup çağrılır.
Effect'in tam olarak tarayıcının boyamasından önce veya sonra çalışacağına güvenilmemelidir. Kullanıcıya görünmeden önce layout ölçümü gibi bir iş yapılması gerekiyorsa
useLayoutEffect ayrı bir kullanım alanıdır. Normal yan etkilerde useEffect tercih edilir.Bağımlılık dizisine göre davranış
Aşağıdaki ayrım, effect'in ne zaman yeniden çalışacağını belirler:
| Kod | Ne zaman çalışır? | Tipik kullanım |
|---|---|---|
useEffect(fn) | Her commit sonrasında | Nadiren gerekir; her çalışmada yan etkiyi bilinçli yönetmek gerekir |
useEffect(fn, [id]) | İlk commit'ten sonra ve id değişince | Seçili kaydı veya URL parametresini izlemek |
useEffect(fn, []) | Bileşen ilk kez commit edildikten sonra; cleanup unmount sırasında | Bileşenin yaşam döngüsüne bağlı kurulumlar |
React her bağımlılığı önceki değerle
Object.is kullanarak karşılaştırır; derin içerik karşılaştırması yapmaz. Dizideki bir nesne, dizi veya fonksiyon her render'da yeniden oluşturuluyorsa içerik aynı görünse bile referansı değişebilir ve effect yeniden çalışabilir. Bu yüzden bağımlılık dizisini eksik yazarak yeniden çalışmayı gizlemek yerine, effect'in kullandığı değerleri doğru biçimde belirtmek gerekir.Somut örnek: id değişince veri çekmek
Aşağıdaki örnekte effect ilk render sonrasında çalışır;
userId değişirse önceki isteğin sonucu artık geçersiz olabileceği için cleanup ile işlem iptal edilir. fetch başarısız olursa hata durumu gösterilir.
JavaScript:
import { useEffect, useState } from "react";
export default function UserCard({ userId }) {
const [user, setUser] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const controller = new AbortController();
let active = true;
setUser(null);
setError(null);
fetch(`https://api.example.com/users/${encodeURIComponent(userId)}`, {
signal: controller.signal
})
.then((response) => {
if (!response.ok) throw new Error("İstek başarısız");
return response.json();
})
.then((data) => { if (active) setUser(data); })
.catch((reason) => {
if (active && reason.name !== "AbortError") setError(reason);
});
return () => {
active = false;
controller.abort();
};
}, [userId]);
if (error) return <p>Veri alınamadı.</p>;
if (!user) return <p>Yükleniyor...</p>;
return <p>{user.name}</p>;
}
Bu bileşen başarıyla çalıştığında önce
Yükleniyor..., istek tamamlanırsa kullanıcının adı görünür. userId değiştiğinde eski istek için iptal istenir ve yeni istek başlatılır. active kontrolü, eski async işin geç gelen sonucunun state’e yazılmasını da engeller; tarayıcının iptal etmesi sunucudaki işi mutlaka durdurmaz. api.example.com yalnızca örnek alan adıdır; gerçek uygulamada kendi API adresinizi kullanmanız gerekir.Uygularken kontrol listesi
- Effect'in gerçekten React dışındaki bir sistemle senkronizasyon yapıp yapmadığını kontrol edin. Yalnızca bir değeri başka bir değerden hesaplıyorsanız bunu render içinde veya
useMemoile hesaplamak daha uygundur. - Effect callback'inin kullandığı props, state ve fonksiyonları bağımlılık dizisine ekleyin.
- Abonelik, zamanlayıcı, olay dinleyicisi veya devam eden istek başlatıyorsanız cleanup döndürün.
- Effect'in beklenenden fazla çalıştığını görürseniz bağımlılıkların referanslarının her render'da değişip değişmediğini inceleyin.
- Geliştirme ortamında aynı kurulum ve cleanup akışını art arda görürseniz Strict Mode davranışını dikkate alın. Cleanup kodu doğruysa üretim davranışını yanlış yorumlamazsınız.
Effect yalnızca istemci tarafında çalışır; sunucu tarafı render sırasında tarayıcıya özgü DOM veya ağ yan etkilerine güvenilmemelidir. Ayrıca effect'in içinden state değiştirmek yeni bir render başlatabileceğinden, bağımlılıkları değişen state'i yeniden yazan bir effect sonsuz döngü oluşturabilir.