Menu

React useLayoutEffect: Tarayıcı Boyamadan Önce Ölçmek

useLayoutEffect useEffect gibi çalışır ama React DOM'u güncelledikten hemen sonra ve tarayıcı boyamadan önce çalışır. Onu bir öğeyi ölçüp yerleşimi görünür bir titreme olmadan ayarlamak için kullan, geri kalan her şey için useEffect'i sakla.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

useLayoutEffect, useEffect'in daha erken çalışan bir sürümüdür: React DOM'u güncelledikten hemen sonra, ama tarayıcı yeni kareyi boyamadan önce. İçindeki kod öğeleri ölçebilir ve yerleşimi değiştirebilir; kullanıcı her zaman yalnızca son sonucu görür. Çalışırken boyamayı engeller, bu yüzden onu yalnızca bu zamanlamaya ihtiyacın olduğunda kullan.

Efektler efekt, layout efekti sırasıyla tanımlanmış, ama konsol her render'da önce layout efektini yazdırıyor. İki hook arasında tanımlama sırası önemli değildir; zamanlamaları önemlidir.

Sözdizimi

İmza useEffect ile aynıdır: bir kurulum fonksiyonu, isteğe bağlı bir temizleme ve bir bağımlılık dizisi.

useLayoutEffect(() => {
    // runs after the DOM update, before paint
    return () => {
        // cleanup, before the next run and on unmount
    };
}, [dependencies]);

useEffect'ten bağımlılıklar ve temizleme hakkında bildiğin her şey geçerlidir. Tek fark React'in onu ne zaman çağırdığıdır.

Her biri ne zaman çalışır

Bir render'dan sonra React DOM'u günceller ve ardından sabit bir sırayla üç şey yapar:

  1. Tüm layout efekti temizlemelerini ve layout efektlerini senkron olarak çalıştırır.
  2. Tarayıcının boyamasına izin verir. Bir layout efekti state ayarladıysa React önce, yine boyamadan önce, yeniden render eder.
  3. Normal efektleri, genellikle boyamadan sonra, çalıştırır.

Bir ağaç genelinde her layout efekti herhangi bir normal efektten önce çalışır ve çocuklar ebeveynlerinden önce çalışır, çünkü bir ebeveyn ancak çocukları yerine oturduğunda bitebilir:

Konsol önce iki layout efektini, önce Child sonra Parent, sonra iki normal efekti aynı sırayla gösterir. key={n} her tıklamada taze bir Parent mount edilmesini sağlar, böylece her seferinde aynı dört satırı alırsın. Her efekte kayıt yazan bir temizleme ekle ve eskilerinin yenilerden önce çalıştığını izle.

Titreme sorunu

Düğmesinin üstünde görünmesi gereken bir tooltip düşün; üstünde yer yoksa altına gider. Tooltip DOM'da olup yüksekliğini ölçebilene kadar üstte yer olup olmadığını bilemezsin. Bu yüzden render iki geçişte olur:

  1. Ölçülebilmesi için tooltip'i bir yere render et.
  2. Onu ölç, gerçek konumu hesapla, state ayarla, yeniden render et.

useEffect ile tarayıcı bu geçişler arasında boyayabilir ve kullanıcı tooltip'in ilk konumdan ikinciye atladığını görür. useLayoutEffect ile ikinci geçiş boyamadan önce olur, bu yüzden ilk konum hiç gösterilmez.

Üstteki düğmenin üzerine gel: üstünde yer yok, bu yüzden tooltip altında görünür. Alttakinin üzerine gel, üstünde görünür. Konsol ölçümün hangi tarafı seçtiğini söyler. useLayoutEffect'i useEffect yap ve yeniden üzerine gel: tooltip artık yer değiştirmeden önce bir kare boyunca kutunun üstünde parlayabilir. Hızlı bir makinede bu çoğu zaman fark edilemeyecek kadar hızlıdır; bu hatanın yayına girip sonra daha yavaş telefonlardan bildirilmesinin nedeni tam olarak budur.

offsetHeight, offsetTop ve getBoundingClientRect() tarayıcıyı yerleşimi hesaplamaya zorlar, bu yüzden onları layout efektinde okumak sana React'in az önce yazdığı DOM'un gerçek değerlerini verir.

Bir öğeyi ölçmek

Aynı kalıp render'ın bağlı olduğu her boyut için çalışır: onu bir layout efektinde bir ref ile oku, state'te sakla, onunla render et.

Düğmeye tıkla; genişlik satırı metinle aynı karede güncellenir. Sayfa yeni bir metnin yanında eski bir genişlik hiç göstermez, çünkü ikinci render boyamadan önce olur. Bağımlılık dizisinden [text]'i kaldır; ölçüm, kendi setWidth'inin yol açtığı dahil her render'dan sonra çalışır; orada durmasının tek nedeni genişliğin artık değişmemesidir.

useEffect'i tercih et

Bir layout efekti dönene kadar, state ayarlarsa ekstra render bitene kadar da boyamayı bekletir. Yavaş bir tanesi sayfadaki her güncellemeyi yavaş hissettirir. useLayoutEffect'i yalnızca bunların hepsi doğru olduğunda kullan:

  • Efekt yerleşimi (boyut, konum, kaydırma) okuyor.
  • Bu okumaya göre render edileni değiştiriyor.
  • Ara durum görünür olur ve yanlış görünürdü.

Geri kalan her şey (veri çekme, abonelikler, zamanlayıcılar, kayıt tutma, analitik) useEffect'e aittir. Hızlı bir kural: useEffect ile başla ve yalnızca bir titreme görürsen geçiş yap.

useEffect genellikle boyamadan sonra çalışır, ama her zaman değil. Güncelleme bir tıklama ya da tuşa basma gibi ayrık bir kullanıcı eyleminden geldiğinde React efektleri tarayıcı boyamadan önce çalıştırabilir. Bir titremenin bir durumda görünüp diğerinde görünmemesinin bir nedeni budur.

Sunucu tarafı render

Efektler sunucu tarafı render sırasında asla çalışmaz, useLayoutEffect de çalışmaz. Sunucu ilk render'ın HTML'ini gönderir ve layout efekti yalnızca tarayıcıda hydration'dan sonra çalışır. React 18 ve öncesi böyle bir bileşen sunucuda render edildiğinde "useLayoutEffect does nothing on the server" uyarısı verirdi; React 19 bu uyarıyı kaldırdı.

Sunucuda render edilen ilk kare ölçüm olmadan yanlış görünecekse iki yaygın çözüm vardır: nötr bir yedek render et (örneğin tooltip'i ölçülene kadar gizle) ya da bileşeni yalnızca istemcide render et:

function ClientOnly({ children }) {
    const [mounted, setMounted] = useState(false);
    useEffect(() => setMounted(true), []);
    return mounted ? children : null;
}

useInsertionEffect

Üçüncü bir efekt hook'u vardır: herhangi bir layout efektinden önce çalışan useInsertionEffect. Çalışma anında <style> etiketleri üreten CSS-in-JS kütüphaneleri için vardır: stilleri orada eklemek, bir öğeyi ölçen bir layout efektinin onu zaten stillendirilmiş görmesi demektir. State güncelleyemez ve ref'ler henüz bağlanmamıştır, bu yüzden uygulama kodunda bir işe yaramaz. Bir stil kütüphanesi yazmıyorsan ona ihtiyacın olmayacak.

Sıkça Sorulan Sorular

useEffect ile useLayoutEffect arasındaki fark nedir?

Zamanlama. useLayoutEffect, React DOM'u değiştirdikten sonra ama tarayıcı boyamadan önce senkron olarak çalışır, bu yüzden state güncellemeleri kullanıcı bir şey görmeden uygulanır. useEffect genellikle boyamadan sonra çalışır. API ve bağımlılık dizisi aynıdır.

useLayoutEffect'i ne zaman kullanmalıyım?

Bir efekt yerleşimi (bir boyut ya da bir konum) okuyup buna göre render edileni hemen değiştirdiğinde; örneğin bir tooltip'i düğmesinin üstüne ya da altına yerleştirirken. O olmadan kullanıcı ilk, yanlış konumu bir kare boyunca görebilir.

useLayoutEffect performans için kötü mü?

Bitene kadar, tetiklediği yeniden render ile birlikte, tarayıcının boyamasını engeller. Yavaş bir layout efekti tüm sayfayı yavaş hissettirir, bu yüzden görünür bir titremeyi önlemen gerekmiyorsa useEffect kullan.

useLayoutEffect sunucuda çalışır mı?

Hayır. Sunucu tarafı render sırasında iki efekt de çalışmaz. Eski React sürümleri useLayoutEffect içeren bir bileşen sunucuda render edildiğinde bir uyarı yazdırırdı; React 19 artık yazdırmaz, ama efekt yine yalnızca tarayıcıda çalışır.

Coddy programlama dilleri çizimi

Coddy ile kodlamayı öğren

BAŞLA