useDeferredValue sana geride kalmasına izin verilen bir değer kopyası verir. Değer değiştiğinde React önce ekranı eski kopyayla yeniden çizer, bu da yazmayı anında tutar, sonra yavaş kısmı arka planda yeni değerle render eder.
Hızlıca bir sözcük yaz. Input yetişir ve liste geride kaldığı sürece soluklaşır. Console her harf için bir SlowList rendering satırı kaydeder, çünkü SlowList React onu render etmeye başlar başlamaz kayıt yazar, ama ara değerler için listeler ekrana hiç ulaşmaz: her yeni harf arka plan render'ını kesti ve React en son metinle baştan başladı. query={deferredQuery} ifadesini query={query} yap ve yeniden yaz: her tuş vuruşu artık liste için çeyrek saniye bekler.
Sözdizimi
const deferredValue = useDeferredValue(value);
const deferredValue = useDeferredValue(value, initialValue); // React 19
valuerender ettiğin herhangi bir şeydir: bir input'tan gelen metin, bir sayı, bir nesne. İlkel değerler en iyi çalışır, çünkü her render'daki yeni bir nesne her zaman bir değişiklik sayılır.- Dönüş değeri çoğu zaman
value'ya eşittir.valuedeğiştikten hemen sonra bir render boyunca hâlâ önceki değeri tutar ve bir arka plan render'ında yetişir.
Nasıl çalışır
Her değişiklik iki render üretir:
- Yeni
valueve eskideferredValueile acil bir render. Input yeni metni gösterir. YalnızcadeferredValuealan bileşenler öncekiyle aynı props'u alır. - Yeni
deferredValueile bir arka plan render'ı. Yavaş olan budur. React onu dilimler hâlinde render eder ve bitmedenvalueyeniden değişirse bırakır, sonra en son değerle baştan başlar.
Bunun olduğunu iki değeri de kaydederek izleyebilirsin:
Tek bir harf yaz, örneğin a; Console iki satır daha yazdırır: önce deferred = "" ile text = "a", sonra ikisi de "a". O ilk render yazmayı hızlı tutan şeydir, ama yalnızca yavaş kısım onu atlayabiliyorsa. İlk örnekteki SlowList'in memo ile sarılmasının nedeni budur: acil render sırasında query prop'u değişmemiştir, bu yüzden React onu atlar. memo olmadan acil render yine tüm yavaş listeyi çalıştırırdı, sadece eski metinle, ve hiçbir şey kazanmazdın.
Eski içeriği göstermek
Arka plan render'ı devam ederken value ile ertelenmiş değer farklıdır. İçeriği gizlemeden kullanıcıya güncel olmadığını söylemek için onları karşılaştır:
const isStale = query !== deferredQuery;
<div style={{ opacity: isStale ? 0.5 : 1, transition: 'opacity 0.2s' }}>
<SlowList query={deferredQuery} />
</div>
Bu genellikle bir spinner'dan daha hoştur: eski sonuçlar okunabilir kalır ve yenileri hazır olduğunda yerinde değişir. Aynı fikir Suspense ile de çalışır: ertelenmiş değer bir bileşenin veri yüklerken askıya alınmasına yol açarsa React, yeni içerik hazır olana kadar yedek içerik yerine eski içeriği göstermeye devam eder (bkz. Suspense ve lazy).
Başlangıç değeri (React 19)
Varsayılan olarak ilk render'ın geride kalacağı bir şey yoktur, bu yüzden ertelenmiş değer baştan gerçek değerdir. React 19'dan beri ikinci bir argüman aktarabilirsin. İlk render'da hook initialValue'yu döndürür, React de sonra arka planda gerçek değerle yeniden render eder. Bu, ucuz bir şeyi hemen gösterip pahalı kısmı hemen ardından doldurmanı sağlar.
Console iki render gösterir: önce "" ile, sonra tam metinle. İkinci argümanı kaldır; yalnızca bir render kaydedilir, doğrudan tam metinle.
useDeferredValue ve useTransition
İkisi de işi acil değil olarak işaretler ve aynı render mekanizmasını kullanır. Fark onları nereye koyduğundadır:
- useTransition güncellemeyi sarar.
startTransition(() => setQuery(text))çağırırsın, bu yüzden setter'a ihtiyacın vardır.isPending'i bedavaya alırsın. - useDeferredValue değeri sarar. Onu değerin kullanıldığı yerde çağırırsın, bu yüzden değer bir prop olarak geldiğinde ya da kontrol etmediğin bir hook'tan geldiğinde çalışır. "Beklemede" durumunu
value !== deferredValueile kendin hesaplarsın.
// You own the state: either works, a transition is direct
startTransition(() => setQuery(nextQuery));
// You only receive the value
function SearchResults({ query }) {
const deferredQuery = useDeferredValue(query);
return <SlowList query={deferredQuery} />;
}
useDeferredValue ile debounce ve throttle
Debounce son değişiklikten sonra sabit bir süre bekler; throttle her aralıkta en fazla bir kez günceller. İkisi de baştan bir gecikme seçer, bu yüzden hızlı bir dizüstü bilgisayarda sayfayı gerektiğinden yavaş yapar, yavaş bir telefonda ise gecikme yine de çok kısa olabilir.
useDeferredValue'nun gecikmesi yoktur. Arka plan render'ı hemen başlar, bu yüzden hızlı bir cihazda liste neredeyse anında güncellenir, yavaş bir cihazda ise React input'u akıcı tutar ve listeyi yapabildiği kadar sık render eder. Arka plan işi ayrıca kesilebilirdir; debounce edilmiş bir render bu değildir: debounce edilmiş bir render başladığında bitene kadar kilitler.
Yapmadığı şey ağ isteklerini azaltmaktır. Her yeni değer bir istek başlatıyorsa ertelenmiş değer tamamlanan her render ile yine değişir, bu yüzden istek sayısı önemliyse isteğin kendisine debounce uygula.
Yaygın hatalar
memo'yu unutmak. Yukarıda gösterildiği gibi yavaş bileşen acil render'ı atlayabilmelidir.memoile sarılmamışsa ya da diğer props'larından biri her render'da yeni bir nesneyse, her tuş vuruşunda bir yerine iki kez render olur.- Yeni bir nesne aktarmak.
useDeferredValue({ query })her render'da yeni bir nesne oluşturur, bu yüzden ertelenmiş değer her zaman değişmiş görünür ve React her seferinde fazladan bir arka plan render'ı başlatır. İlkel değeri ertele (useDeferredValue(query)) ve nesneleri ondan oluştur. - Daha az istek beklemek. Ertelenmiş değere göre veri çeken bir bileşen, render'ı biten her değer için yine veri çeker.
Ne zaman başvurmalı
Tek bir input sayfanın render'ı yavaş bir kısmını yönettiğinde, yavaş kısım memoize edilebildiğinde ve bir an için biraz eski sonuçlar göstermek sana uyduğunda useDeferredValue kullan: arama sonuçları, bir filtreden yeniden çizilen bir grafik, biçimlendirilmiş metnin önizlemesi. Yavaş kısım düzeltebileceğin bir nedenle yavaşsa, örneğin 50'si görünürken 5.000 satır render etmek, önce onu düzelt. Setter'a sahip olduğun sürümü için bkz. useTransition.
Sıkça Sorulan Sorular
useDeferredValue ne yapar?
Bir değerin gerçeğinden geride kalabilen bir sürümünü döndürür. Değer değiştiğinde React önce eski ertelenmiş değerle render eder, sonra arka planda yenisiyle yeniden render eder ve bu arka plan render'ı yarıda kesilebilir.
useDeferredValue listemi neden hızlandırmıyor?
Yavaş bileşen memo ile sarılmalı ve ertelenmiş değeri almalıdır. Aksi hâlde acil render yavaş bileşeni yine render eder, sadece eski değerle, ve yazma yavaş kalır.
useDeferredValue ile useTransition arasındaki fark nedir?
useTransition state güncellemesini sarar, bu yüzden setter'a erişimin olması gerekir. useDeferredValue bir değeri sarar, bu yüzden değeri yalnızca aldığında çalışır; örneğin bir prop olarak ya da kontrol etmediğin bir hook'tan.
useDeferredValue bir debounce mu?
Hayır. Sabit bir gecikme yoktur. React ertelenmiş render'ı acil olanın hemen ardından başlatır ve hızlı bir cihazda gecikme zar zor görünür. Ayrıca kendi başına ağ isteklerini azaltmaz.
useDeferredValue'nun ikinci argümanı nedir?
React 19'dan beri bir initialValue aktarabilirsin. İlk render'da hook onu döndürür, sonra React arka planda gerçek değerle yeniden render eder.