React.memo mi useCallback mi useMemo mi? Performans Optimizasyonu Seçimi
React uygulamalarında gereksiz render'lar, kullanıcı deneyimini doğrudan etkileyen performans sorunlarına yol açar. Bir component'in props'u veya state'i değişmese bile yeniden render edilmesi, özellikle karmaşık uygulamalarda ciddi hızlanma kayıplarına neden olur. Bu noktada geliştiriciler üç temel optimizasyon tekniği arasında seçim yapmak zorunda kalır: React.memo, useCallback ve useMemo. Her biri farklı sorunlara çözüm sunarken, hangi durumda hangisini kullanacağını bilmek uzun vadeli bir uygulamanın başarısını belirler.
React.memo: Component Düzeyinde Koruma
React.memo, bir functional component'i sarmalayan üst seviye bir optimizasyon aracıdır. Temel işlevi basittir: component'e gelen props'lar değişmemişse, o component'in yeniden render edilmesini engeller. Bu yaklaşım, parent component render olduğunda child component'lerin gereksiz yere güncelenmesini önlemek için idealdir.
React.memo'nun avantajları:
- Uygulanması en kolaydır—sadece component'i sarmalarsınız
- Child component'lerde props karşılaştırması otomatik yapılır
- Büyük component ağaçlarında parent render'ları sırasında etkili bir engelleyici görevi görür
Sınırlamalar:
- Sadece props değişimini kontrol eder; state değişimleri bunu atlar
- Nesne veya fonksiyon tipinde props'lar her zaman "yeni" kabul edilir (referans eşitliği sorunu)
- Yüzeysel karşılaştırma yapar—iç içe nesneleri derinlemesine kontrol etmez
useCallback: Fonksiyon Referansını Sabitlemek
useCallback hook'u, fonksiyon tipindeki props'ların her render sırasında yeni referanslar almasını önler. Bir parent component'ten child component'e bir fonksiyon props olarak geçiliyorsa ve child component React.memo ile korunuyorsa, fonksiyon referansı değişmemesi gerekir. İşte burada useCallback devreye girer.
Teknik olarak useCallback, bir fonksiyonun memoized versiyonunu döndürür. Dependency array'inde listelenen değerler değişmediği sürece, aynı fonksiyon referansı korunur. Bu sayede React.memo korumalı child component'ler gereksiz render'dan kurtulur.
useCallback'in güçlü yanları:
- Callback fonksiyonlarını event handler'lar aracılığıyla child'a geçerken özel olarak yararlıdır
- Dependency array kontrolü sayesinde fine-grained kontrole izin verir
- useEffect ile birlikte kullanıldığında infinite loop'ları engeller
Potansiyel problemler:
- Yanlış dependency array tanımı, eski fonksiyon referanslarının kullanılmasına neden olabilir
- Her useCallback tanımı hafızada tutulur—aşırı kullanım memory overhead'e sebep olur
- Küçük uygulamalarda gereksiz komplekslik ekleyebilir
useMemo: Hesaplamalar İçin Memoizasyon
useMemo, fonksiyonlardan ziyade hesaplanan değerleri memoize eder. Bir component render edildiğinde yoğun hesaplamalar (filtering, sorting, mapping gibi) yapılıyorsa, bu hesaplamanın sonucu useMemo ile saklanabilir ve dependency array değişmediği sürece yeniden hesaplanmaz.
Özellikle büyük veri setleriyle çalışan veya kompleks algoritma gerektiren uygulamalarda useMemo çarpıcı performans farkları yaratabilir. Ancak herkes için uygun değildir—yalnızca ölçülebilir performans sorunları varsa kullanılmalıdır.
useMemo'nun en etkili olduğu senaryolar:
- Bin-element listelerinde filter veya sort işlemleri
- Matematiksel hesaplamalar veya veri dönüştürmeler
- Nesne veya dizi oluşturmalar (referans eşitliği gerekmiyorsa)
Dikkat edilmesi gerekenler:
- Memoizasyon işleminin kendisi de bir maliyettir—basit hesaplamalar için zarara uğrayabilir
- Kullanmadan önce React DevTools Profiler ile gerçek performans darboğazını tespit etmek şarttır
- Dependency array yönetimi karmaşık hale gelebilir
Hangisini Ne Zaman Seçmeli?
Üç teknik arasında seçim yaparken karar ağacı basittir:
React.memo'yu kullanın: Parent component sık sık render olunca, child component'lerin gereksiz yere güncellendiğini gözlemlediyseniz ve child component'lerin props'ları nadiren değişiyorsa.
useCallback'i ekleyin: React.memo korumalı bir component'e callback props geçiyorsanız veya bir callback'in useEffect dependency'si oluyorsa.
useMemo tercih edin: Hesaplamalar açıkça yavaş olduğunu gördüyseniz (Profiler ile ölçülmüş) ve bu hesaplamalar expensive işlemler içeriyorsa.
Altın kural: Optimizasyon başlamadan önce ölçün. Spekülasyon yerine React DevTools Profiler'ı açın ve gerçek performans sorunlarını tespit edin.
Karşılaştırma Tablosu
| Teknik | Koruma Alanı | Uygulama Karmaşıklığı | Bellek Maliyeti | İdeal Durum |
|---|---|---|---|---|
| React.memo | Component render'ı | Çok düşük | Minimal | Props nadiren değişen child'lar |
| useCallback | Fonksiyon referansı | Orta | Düşük-Orta | Callback props'ları ve dependencies |
| useMemo | Hesaplanan değer | Orta-Yüksek | Orta-Yüksek | Ağır hesaplamalar |
React performans optimizasyonunda tek bir "doğru" cevap yoktur. Bağlam, uygulamanın mimarisi ve gerçek bottleneck'ler belirleyicidir. Eğitim karşılaştırması rehberlerine benzer şekilde, burada da ihtiyaçlarınızı önce tanımlayıp sonra uygun aracı seçmek gerekir. Gereksiz optimizasyon karmaşıklığa, saklanmış hatalar ve bakım zorlukları yaratır. Ölçülebilir sorunlar varsa uygun tekniği seçmek, yoksa sade kodu tercih etmek React geliştirmenin en iyi pratiğidir.