React uygulamalarında performans, özellikle büyük bileşen ağaçlarında ve sık güncellenen state'lerde kritik hale gelir. Gereksiz render'ları engellemek için React'in sunduğu üç ana araç vardır: useMemo, useCallback ve React.memo. Bu araçlar birbirine benzese de farklı amaçlara hizmet eder. Bu yazıda, her birini derinlemesine inceleyecek, hangi durumda hangisinin kullanılması gerektiğini karşılaştırmalı olarak ele alacağız.
Gereksiz Render Problemi
React, bir bileşenin state'i veya props'ı değiştiğinde o bileşeni ve alt bileşenlerini yeniden render eder. Ancak çoğu zaman alt bileşenlerin değişmeyen props'ları vardır ve yeniden render edilmeleri gereksizdir. Büyük listeler, grafikler veya karmaşık hesaplamalar bu durumda performans kaybına yol açar. useMemo, useCallback ve React.memo bu sorunu çözmek için tasarlanmıştır. Örneğin, React'te Intersection Observer ile Sonsuz Kaydırma gibi bileşenlerde performans optimizasyonu hayati önem taşır.
useMemo: Pahalı Hesaplamaları Önbelleğe Al
useMemo, bir fonksiyonun dönüş değerini, bağımlılıkları değişmediği sürece hatırlar (memoize). Genellikle pahalı hesaplamaların sonucunu önbelleğe almak için kullanılır. Örneğin, büyük bir diziyi filtrelemek veya sıralamak gibi işlemlerde useMemo kullanarak aynı girdilerle tekrar tekrar hesaplama yapılmasını önleyebilirsiniz.
Kullanım Örneği
const sortedData = useMemo(() => expensiveSort(data), [data]);
Burada sortedData, yalnızca data değiştiğinde yeniden hesaplanır. useMemo, bir referans eşitliği kontrolü sağlar ve sonucu her render'da yeniden üretmez.
useCallback: Fonksiyon Referanslarını Koru
useCallback, bir fonksiyonun kendisini memoize eder. Yani, bağımlılıklar değişmediği sürece aynı fonksiyon referansını döndürür. Bu özellikle, alt bileşenlere callback prop'ları geçerken ve alt bileşen React.memo ile sarılmışsa önemlidir. Çünkü her render'da yeni bir fonksiyon oluşturulması, React.memo'nun çalışmasını engeller.
Kullanım Örneği
const handleClick = useCallback(() => { doSomething(id); }, [id]);
handleClick, id değişmediği sürece aynı referansa sahip olur. Bu sayede alt bileşen gereksiz yere render edilmez.
React.memo: Bileşen Render'ını Kontrol Et
React.memo, bir bileşeni saran bir higher-order component'tir. Bileşenin props'larını yüzeysel olarak karşılaştırır ve eğer props'lar değişmemişse bileşenin render edilmesini engeller. Fonksiyonel bileşenler için PureComponent görevi görür. Ancak props içinde fonksiyonlar veya nesneler varsa, bunlar her render'da yeni referans alacağı için React.memo tek başına yeterli olmayabilir. Bu durumda useCallback veya useMemo ile birlikte kullanılmalıdır.
Kullanım Örneği
const Child = React.memo(({ onClick, data }) => { ... });
Child bileşeni, onClick veya data referansı değişmediği sürede yeniden render edilmez.
Karşılaştırma Tablosu
| Özellik | useMemo | useCallback | React.memo |
|---|---|---|---|
| Memoize edilen şey | Değer (value) | Fonksiyon (function) | Bileşen (component) |
| Kullanım yeri | Bileşen içinde | Bileşen içinde | Bileşen dışında (sarıcı) |
| Props karşılaştırması | Yok | Yok | Yüzeysel (shallow) |
| Bağımlılık dizisi | Evet | Evet | Hayır (props bazında) |
| Amaç | Pahalı hesaplamaları önlemek | Fonksiyon referansını sabit tutmak | Gereksiz bileşen render'ını önlemek |
Ne Zaman Hangisi Kullanılmalı?
Her aracı doğru yerde kullanmak önemlidir. İşte pratik bir kılavuz:
- useMemo: Bir hesaplama pahalıysa (örneğin, büyük bir diziyi filtreleme, karmaşık matematiksel işlemler) ve bağımlılıklar sık değişmiyorsa kullanın. Her yerde kullanmak performansı iyileştirmez, aksine memory overhead ekler.
- useCallback: Fonksiyonları alt bileşenlere prop olarak geçiriyorsanız ve alt bileşen
React.memoile sarılmışsa kullanın. Özellikle olay işleyicilerde faydalıdır. - React.memo: Bileşenin props'ları sık sık değişmiyorsa ve bileşende ağır bir render işlemi varsa kullanın. Ancak aşırı kullanmaktan kaçının; her bileşeni sarmak performans testi gerektirir.
Önemli bir nokta: Bu araçları gereksiz yere kullanmak, kod karmaşıklığını artırır ve bazen performansı düşürebilir. Önce profilleme yapın, darboğazları tespit edin ve ardından optimize edin. Örneğin, React'te useRef Hook'unun Derinlemesine Kullanımı da performans odaklıdır ancak DOM manipülasyonu için kullanılır.
Sık Yapılan Hatalar
Geliştiricilerin en yaygın hatalarından biri, useMemo ve useCallback'i her fonksiyon ve değer için kullanmaktır. Bu, gereksiz bellek kullanımına ve okunabilirlik kaybına yol açar. Ayrıca, bağımlılık dizisini yanlış belirlemek veya boş bırakmak ([] gibi) beklenmedik davranışlara neden olabilir. React.memo kullanırken, props içindeki nesne veya dizilerin her render'da yeni referans alacağını unutmayın; bu durumda useMemo ile props'ları sabitlemek gerekir.
Sonuç: Doğru Araçla Performansı Artırın
useMemo, useCallback ve React.memo, React performansını optimize etmek için güçlü araçlardır. Ancak her biri farklı bir senaryoya hitap eder. Pahalı hesaplamalar için useMemo, fonksiyon referanslarını korumak için useCallback, ve bileşen düzeyinde render kontrolü için React.memo kullanın. Unutmayın: Optimizasyon, ihtiyaç duyulduğunda yapılmalıdır. Önce uygulamanızı profilleyin, darboğazları bulun ve ardından bu araçları stratejik olarak uygulayın. Bu yaklaşım, hem performansı artırır hem de kodunuzu temiz tutar.
Sık Sorulan Sorular
useMemo ve useCallback arasındaki temel fark nedir?
useMemo bir değeri (value) memoize ederken, useCallback bir fonksiyonu memoize eder. useMemo pahalı hesaplamaların sonucunu önbelleğe alır, useCallback ise fonksiyon referansının sabit kalmasını sağlar.
React.memo ne zaman kullanılmalıdır?
React.memo, bir bileşenin props'ları değişmediğinde yeniden render edilmesini engellemek için kullanılır. Özellikle sık sık aynı props'larla render edilen ve ağır işlemler yapan bileşenlerde faydalıdır.
useMemo her yerde kullanılmalı mı?
Hayır, useMemo'yu gereksiz yere kullanmak bellek kullanımını artırır ve kod karmaşıklığına yol açar. Sadece pahalı hesaplamalar ve belirgin performans sorunları olduğunda kullanılmalıdır.






