- Published
⚛️ React’ta Memoization
React ile çalışırken sayfanın yavaşladığını, bazı bileşenlerin tekrar tekrar render olduğunu fark etmiş olabilirsin. Özellikle filtreleme, sepete ürün ekleme, ürün listeleri gibi dinamik yapıların olduğu bir e-ticaret uygulamasında bu durum daha da belirgin hale gelir.
İşte bu noktada memoization, yani değerleri hafızada tutmak, performansı iyileştirmek için önemli bir araçtır.
Ama bu araç doğru yerde kullanılmazsa, performansa katkı sağlamak yerine karmaşıklık yaratır. Bu yazıda useMemo
, useCallback
ve React.memo
hook'larının ne işe yaradığını, ne zaman işe yaramadığını ve en sağlıklı nasıl kullanıldığını detaylıca anlatıyorum.
Memoization Nedir?
Memoization, bir işlemin sonucunu hafızada tutarak, aynı girdilerle tekrar karşılaşıldığında o sonucu yeniden hesaplamadan döndürmektir.
React'te bu, özellikle render süreçlerini optimize etmek amacıyla kullanılır.
Kısa Tanımlar
React.memo
Bir functional component’i sarar. Eğer props'ları değişmemişse, component'in yeniden render edilmesini engeller.
📌 Ne işe yarar?
Gereksiz render'ları engeller. Yüzeysel (shallow) prop karşılaştırması yapar.
useMemo
Bir değerin (genellikle hesaplama sonucu) cache'lenmesini sağlar.
📌 Ne işe yarar?
Maliyetli hesaplamaları gereksiz yere tekrar etmemek için kullanılır.
useCallback
Bir fonksiyonun referansını cache’ler, bağımlılıklar değişmediği sürece aynı fonksiyon referansını korur.
📌 Ne işe yarar?
Fonksiyonları prop olarak geçerken gereksiz render’ları engeller.
🔔 Not: Bu üçü sadece re-render sırasında etkilidir. İhtiyaç dışında her yerde kullanmak ilk render'da performansı düşürür.
📌 useMemo
ve useCallback
, primitive değil, referans tipleri (object, array, function) için anlamlıdır.
Örnekler ile Memoization
1. React.memo – Sipariş Geçmişi Ürün Kartı Örneği
import { memo } from "react";
type Product = {
id: number;
name: string;
price: number;
image: string;
};
type Props = {
product: Product;
};
const OrderProductCard = ({ product }: Props) => {
return (
<div className="order-product-card">
<img src={product.image} alt={product.name} loading="lazy" />
<h3>{product.name}</h3>
<p>{product.price} ₺</p>
</div>
);
};
export default memo(OrderProductCard);
✅ Ne zaman işe yarar?
- Kullanıcının geçmiş siparişleri listeleniyorsa ve ürün verisi sabitse,
product
objesi aynı referansta kaldığı sürece bu bileşen tekrar render edilmez.- Büyük sipariş geçmişi listelerinde performansa katkı sağlar.
⚠️ Not: React.memo
, props’lar üzerinde shallow (yüzeysel) karşılaştırma yapar.
Eğer prop olarak verdiğiniz obje her render’da yeniden oluşturuluyorsa ({ id: 1, name: 'Test' }
gibi), React.memo
işe yaramaz. Bu gibi durumlarda useMemo
ile dışarıda tanımlamak daha verimlidir.
🛠️ 2. useMemo – Ürün Filtreleme
const ProductList = ({ products, selectedCategories }: Props) => {
const filteredProducts = useMemo(() => {
return products.filter((product) =>
selectedCategories.includes(product.category)
);
}, [products, selectedCategories]);
return (
<div className="grid">
{filteredProducts.map((product) => (
<OrderProductCard key={product.id} product={product} />
))}
</div>
);
};
✅ Ne zaman işe yarar?
products
çok sayıda üründen oluşuyorsa,- Filtreleme işlemi maliyetliyse,
- Render sırasında her seferinde tekrar hesaplanması istenmiyorsa katkı sağlar.
❗ Ne zaman işe yaramaz?
- Liste küçükse,
- Filtreleme basitse,
- Sadece alışkanlıkla yazıldıysa (ki sık sık bu oluyor) işe yaramaz.
🛠️ 3. useCallback – Sepete Ürün Ekleme Fonksiyonu
const onAddToCart = useCallback((productId) => {
dispatch(addToCart(productId));
}, [dispatch]);
✅ Ne zaman işe yarar?
- Bu fonksiyon
React.memo
ile sarılmış bir bileşene prop olarak veriliyorsa, - Fonksiyon her render’da yeniden tanımlanmasın isteniyorsa işe yarar.
❗ Ne zaman işe yaramaz?
- Fonksiyon DOM elemanına doğrudan veriliyorsa,
- Fonksiyon başka bir bileşene prop olarak gitmiyorsa,
- Bileşenin kendisi zaten
React.memo
ile sarmalanmamışsa işe yaramaz.
Her Yerde Kullanmalı mıyız?
Hayır. Memoization doğru yerde kullanılırsa faydalıdır, ama yanlış yerde:
- Kodun karmaşıklığını artırır.
- Gereksiz bellek kullanımı yaratır.
- İlk render süresini uzatır.
- Bakımı zorlaştırır.
🔻Yanlış Kullanım Örneği 1:
const Summary = () => {
const total = useMemo(() => 100 + 200, []);
return <p>Toplam: {total} ₺</p>;
};
Bu gibi sabit ve basit işlemler için useMemo
kullanmak gereksizdir. Bu işlem zaten hızlıdır, memoization sadece ekstra yük getirir.
🔻Yanlış Kullanım Örneği 2:
const Button = () => {
const handleClick = useCallback(() => {
console.log("Clicked");
}, []);
return <button onClick={handleClick}>Tıkla</button>;
};
Eğer bu handleClick
fonksiyonu başka bileşene prop olarak geçmiyorsa, useCallback
kullanmak anlamsızdır. Çünkü render davranışını etkilemez.
“Ölçmeden Optimize Etme”
Memoization uygulamadan önce gerçekten bir performans problemi olup olmadığını belirlemek gerekir.
Ne Kullanabilirim?
- React Developer Tools – bileşen render’larını izlemek için
- React Profiler + console.log – hangi bileşen ne zaman render oluyor?
- Chrome DevTools Performance Tab – render sürelerini analiz etmek için
Gereksiz render yoksa, optimize etmeye çalışmak fayda sağlamaz. Önce ölç, sonra iyileştir.
Sonuç olarak React’te memoization, doğru kullanıldığında uygulamanın performansını hissedilir şekilde artırabilir.
Özellikle ürün listeleri, sipariş geçmişi, filtreleme, sepet gibi e-ticaret senaryolarında etkisi büyüktür.
Ama her yerde kullanmak doğru değildir. Doğru karar, ölçüm ve kullanım bağlamına göre verilmelidir.
Bu yazıda, React.memo
, useMemo
, useCallback
araçlarını ne zaman ve nasıl kullanmak gerektiğini, örneklerle ve açıklamalarla paylaştım.
Küçük bir optimizasyon, büyük bir kullanıcı deneyimi farkı yaratabilir.
Okuduğun için teşekkürler 💐
Elif