- Konu sahibi
- #1
Gereksiz yeniden render'ı tespit etmenin en güvenilir yolu, önce React DevTools Profiler ile hangi bileşenin ne zaman ve neden render olduğunu gözlemlemek, ardından bileşene geçici
Bir bileşen state güncellemesiyle, üst bileşenin render akışıyla veya tükettiği context değişimiyle yeniden değerlendirilebilir. Prop kendi başına bağımsız bildirim sistemi değildir; yeni prop üst render üzerinden gelir. memo, aynı prop’larda bu işi atlamaya yardımcı olabilir; aynı state değerinde de React Object.is karşılaştırmasıyla güncellemeyi atlayabilir. Context kullanan bileşenler, ilgili context değeri değiştiğinde de etkilenir. React'in bir bileşeni yeniden değerlendirmesi, tarayıcı DOM'unun mutlaka değiştiği anlamına gelmez; React sonunda gerçek DOM değişikliğine ihtiyaç olup olmadığını ayrıca belirler.
Örneğin üst bileşen her çalıştığında doğrudan yazılmış yeni bir nesne veya fonksiyon prop'u oluşturulabilir:
Beklenen sonuç, belirli etkileşim ile belirli commit'ler arasında anlaşılır bir ilişki kurabilmenizdir. Bir input değişiminde uygulamanın geniş bir bölümü tekrar çalışıyor ve ölçülen süre etkileşimi yavaşlatıyorsa prop zinciri, ortak üst state veya geniş kapsamlı context ilk incelenecek yerlerdir.
Aşağıdaki ayrım hangi müdahalenin uygun olduğunu seçmeye yardımcı olur:
Örneğin yalnızca
Profiling ölçüm maliyeti ekler; normal üretim derlemesinde programatik Profiler ölçümü varsayılan olarak kapalıdır. Üretimde profilleme için desteklenen özel profiling build gerekir. React Compiler etkinse otomatik memoization da sonucu etkileyebilir.
Render sayısını tek başına performans ölçüsü sanmak: Kısa süren bir render sorun olmayabilir; az sayıdaki pahalı render daha önemli olabilir.
console.log çıktısını üretim davranışı kabul etmek: Geliştirme araçları ve geliştirme modu gözlemi etkileyebilir. Kararı Profiler süresi, kullanıcı etkileşimi ve gerçek darboğazla birlikte verin.
Her prop'u useMemo veya useCallback ile sarmalamak: Önce referansın gerçekten gereksiz render tetiklediğini kanıtlayın. Bağımlılık dizisi yanlışsa eski veri kullanmak gibi yeni hatalar doğabilir.
DOM değişmedi diye render olmadığını varsaymak: React bileşeni çalışmış, fakat sonuç DOM güncellemesi gerektirmemiş olabilir. Tespitte bileşen render'ı ile DOM değişikliğini ayrı değerlendirin.
Evet. Şüpheli bileşene geçici
Hayır.
Hayır. Önce hangi kullanıcı etkileşiminin bu render'ı tetiklediğini ve sürenin gerçekten sorun oluşturup oluşturmadığını belirleyin. Sonra tek bir değişiklik yapıp aynı etkileşimi yeniden profilleyin.
console.count() veya console.log() ekleyerek davranışı küçük bir örnekte doğrulamaktır. Bir bileşenin tekrar render olması tek başına hata değildir; sorun, değişmeyen veriye rağmen pahalı hesaplama veya büyük alt ağaçların gereksiz çalışmasıdır.Yeniden render ne zaman gerçekleşir?
Bir bileşen state güncellemesiyle, üst bileşenin render akışıyla veya tükettiği context değişimiyle yeniden değerlendirilebilir. Prop kendi başına bağımsız bildirim sistemi değildir; yeni prop üst render üzerinden gelir. memo, aynı prop’larda bu işi atlamaya yardımcı olabilir; aynı state değerinde de React Object.is karşılaştırmasıyla güncellemeyi atlayabilir. Context kullanan bileşenler, ilgili context değeri değiştiğinde de etkilenir. React'in bir bileşeni yeniden değerlendirmesi, tarayıcı DOM'unun mutlaka değiştiği anlamına gelmez; React sonunda gerçek DOM değişikliğine ihtiyaç olup olmadığını ayrıca belirler.
Örneğin üst bileşen her çalıştığında doğrudan yazılmış yeni bir nesne veya fonksiyon prop'u oluşturulabilir:
Kod:
function Panel({ count }) {
const options = { theme: "light" };
const onSelect = () => console.log("select");
return <Child count={count} options={options} onSelect={onSelect} />;
}
Panel yeniden render olduğunda options ve onSelect yeni referanslara sahip olur. Child React.memo ile sarmalanmış olsa bile bu prop'lar değişmiş kabul edilir.Adım adım tespit
- Geliştirme ortamında React DevTools'u açın ve
Profilersekmesine geçin. Kayda başlamadan önce ölçmek istediğiniz ekranı veya bileşen alt ağacını belirleyin. - Profil kaydını başlatın, yalnızca bir eylem gerçekleştirin: örneğin bir input'a tek karakter yazın veya bir düğmeye bir kez basın. Kaydı durdurun; çok sayıda eylemi aynı kayda karıştırmayın.
- Commit'leri inceleyin. Hangi bileşenlerin her commit'te tekrar çalıştığına, Profiler’da bildirilen render sürelerine ve tek bir etkileşimin çok sayıda bileşeni tetikleyip tetiklemediğine bakın.
- Şüpheli bileşene geçici bir sayaç ekleyin. Bu sayaç yalnızca geliştirme teşhisi içindir:
Kod:function ProductList({ products }) { console.count("ProductList render"); return products.map(product => ( <div key={product.id}>{product.name}</div> )); } - Sayaç beklenmeyen şekilde artıyorsa, bileşenin state'ini, üst bileşenden gelen prop referanslarını ve kullandığı context'i karşılaştırın. Aynı görünen nesne veya dizinin gerçekten her render'da yeniden oluşturulup oluşturulmadığını kontrol edin.
- Değişikliğin etkisini yeniden ölçün. Render sayısı azalsa bile toplam sürenin azalıp azalmadığını kontrol edin; amaç yalnızca sayacı düşürmek değil, gereksiz işi azaltmaktır.
Beklenen sonuç, belirli etkileşim ile belirli commit'ler arasında anlaşılır bir ilişki kurabilmenizdir. Bir input değişiminde uygulamanın geniş bir bölümü tekrar çalışıyor ve ölçülen süre etkileşimi yavaşlatıyorsa prop zinciri, ortak üst state veya geniş kapsamlı context ilk incelenecek yerlerdir.
Sonucu nasıl yorumlamalı?
Aşağıdaki ayrım hangi müdahalenin uygun olduğunu seçmeye yardımcı olur:
| Gözlem | Muhtemel neden | İlk sonraki adım |
|---|---|---|
| Üst bileşenle birlikte alt bileşen de her seferinde çalışıyor | Değişen state veya yeni prop referansı | Prop'ları ve state'in bulunduğu seviyeyi inceleyin |
| React.memo olmasına rağmen alt bileşen çalışıyor | Nesne, dizi veya fonksiyon prop'u yeni referans taşıyor | Gerekirse useMemo veya useCallback kullanın; önce ölçün |
| Bileşen az çalışıyor ama commit uzun sürüyor | Render içindeki pahalı hesaplama veya büyük liste | Profiler süresini ve hesaplamanın kapsamını inceleyin |
| Beklenenden fazla sayaç artışı yalnızca geliştirmede görülüyor | Geliştirme denetimleri veya Strict Mode davranışı | Üretim davranışıyla karıştırmadan aynı etkileşimi kontrollü karşılaştırın |
Örneğin yalnızca
count değişirken options nesnesi her seferinde yeniden oluşturuluyorsa, seçenekleri sabit bir kapsamda tutmak veya gerçekten bağımlı olduğu değerlerle useMemo içinde üretmek düşünülebilir. Fonksiyon prop'u için de aynı şekilde useCallback kullanılabilir. Ancak her bileşeni otomatik olarak memo'lamak doğru yaklaşım değildir; bağımlılıkları karmaşıklaştırabilir ve ölçülebilir bir kazanç sağlamayabilir.Profiling ölçüm maliyeti ekler; normal üretim derlemesinde programatik Profiler ölçümü varsayılan olarak kapalıdır. Üretimde profilleme için desteklenen özel profiling build gerekir. React Compiler etkinse otomatik memoization da sonucu etkileyebilir.
Sık yapılan hatalar
Render sayısını tek başına performans ölçüsü sanmak: Kısa süren bir render sorun olmayabilir; az sayıdaki pahalı render daha önemli olabilir.
console.log çıktısını üretim davranışı kabul etmek: Geliştirme araçları ve geliştirme modu gözlemi etkileyebilir. Kararı Profiler süresi, kullanıcı etkileşimi ve gerçek darboğazla birlikte verin.
Her prop'u useMemo veya useCallback ile sarmalamak: Önce referansın gerçekten gereksiz render tetiklediğini kanıtlayın. Bağımlılık dizisi yanlışsa eski veri kullanmak gibi yeni hatalar doğabilir.
DOM değişmedi diye render olmadığını varsaymak: React bileşeni çalışmış, fakat sonuç DOM güncellemesi gerektirmemiş olabilir. Tespitte bileşen render'ı ile DOM değişikliğini ayrı değerlendirin.
Kaynaklar
Sık sorulan sorular
React DevTools olmadan kontrol edebilir miyim?
Evet. Şüpheli bileşene geçici
console.count("Bilesen render") ekleyerek tekrarları görebilirsiniz. Bu yöntem nedeni ve süreyi ayrıntılı göstermez; neden analizi için prop, state ve context karşılaştırmasını ayrıca yapmanız gerekir.React.memo render'ı tamamen engeller mi?
Hayır.
React.memo varsayılan olarak her prop’u Object.is ile karşılaştırır. Yeni nesne, dizi veya fonksiyon referansları farklı kabul edilir; ayrıca bileşenin kendi state'i veya kullandığı context değişirse yeniden render olabilir.Profiler'da her render kırmızı görünüyorsa hemen optimizasyon yapmalı mıyım?
Hayır. Önce hangi kullanıcı etkileşiminin bu render'ı tetiklediğini ve sürenin gerçekten sorun oluşturup oluşturmadığını belirleyin. Sonra tek bir değişiklik yapıp aynı etkileşimi yeniden profilleyin.