React'ta Performans Optimizasyon Kancası useCallback
Bu derste, aşağıdaki performans optimizasyon kancasını inceleyeceğiz:
useCallback.
useCallback kancası, useMemo API'sine benzer,
aradaki fark, birincisinin ekran yeniden render'ları arasında
değeri önbelleğe alması, ikincisinin ise bir geri çağırma fonksiyonunu önbelleğe almasıdır.
Bu, kaynak yoğun işlevleri gerekmediğinde yeniden çalıştırmamamıza olanak tanır ve
bir işlevin
alt bileşenlere aktarılması durumunda kullanılabilir.
Bir örnekle daha iyi anlayalım.
Öncelikle bir App bileşeni oluşturalım
ve içinde bir num state'i tanımlayalım:
const [num, setNum] = useState(0);
Tıklanınca num değerini
1 artıran bir butonumuz olsun,
ve num değerini göstereceğimiz bir paragrafımız olsun:
return (
<div>
<button onClick={() => setNum(num + 1)}>tıkla</button>
<p>tıklamalar: {num}</p>
</div>
);
Şimdi, varsayalım ki App içinde
başka bir butona tıklandığında eklenen
bir öğe listesi daha gösteriliyor.
Bu liste öğelerini saklamak için
bir items state'i tanımlayalım:
const [items, setItems] = useState([]);
Ardından, onları eklemek için bir addItem
fonksiyonu yazalım:
function addItem() {
setItems([...items, 'yeni öğe']);
}
Şimdi liste öğelerini görüntülemek için kod yazalım
ve onu, prop olarak öğe dizisini ve ekleme fonksiyonunu
alan alt bileşen Items'e taşıyalım.
Items bileşenimizin ne zaman
yeniden render edildiğini görmek için
konsola çıktı vermeyi unutmayalım:
function Items({ items, addItem }) {
const result = items.map((item, index) => {
return <p key={index}>{item}</p>;
});
console.log('Items render ediliyor');
return (
<div>
<h3>Öğelerimiz</h3>
{result}
<button onClick={addItem}>öğe ekle</button>
</div>
);
}
export default Items;
Items bileşenini App bileşeninin
sonuna yerleştirelim ve ona items dizisini
ve öğe ekleme fonksiyonu addItem'ı prop olarak geçelim:
return (
<>
<div>
<button onClick={() => setNum(num + 1)}>tıkla</button>
<p>tıklamalar: {num}</p>
<br />
</div>
<Items items={items} addItem={addItem} />
</>
);
Şimdi butonlara tıklayalım ve
num'ın arttığını ve
listeye yeni öğeler eklendiğini görelim.
Konsolu açtığımızda, listemizin
num'ı artıran butona her tıkladığımızda
bile her seferinde yeniden render edildiğini göreceğiz.
Eğer küçük bir listemiz varsa sorun yok,
peki ya hacimli olacağı ve içinde daha birçok şey
olacağı varsayılıyorsa?
Sorun değil - diyebilirsiniz, çünkü geçen
derste, bileşenin gereksiz yeniden render'larından
kaçınmak için tam da memo API'sini inceledik.
Öyleyse Items bileşenimizi memo ile sarmalayalım ve işte bu kadar.
Bu arada, bu Items'ı dışa aktarırken doğrudan yapılabilir:
export default memo(Items);
memo'yu içe aktarmayı unutmayalım:
import { memo } from 'react';
Şimdi konsolu açalım ve butonlara tıklayalım.
Tüm çabalar boşuna! Bileşeni memoize ettik,
ancak 'tıkla' butonuna tıklandığında
Items bileşeni yine de her seferinde
yeniden render oluyor.
Bunun nedeni, üst bileşen yeniden render edildiğinde,
onun fonksiyonlarının yeniden oluşturulmasıdır - bu,
Items'a aktardığımız addItem
fonksiyonumuz için de geçerlidir.
İşte tam bu noktada useCallback kancası bize yardımcı olacaktır.
Haydi uygulayalım. Öncelikle onu App bileşenine içe aktaralım:
import { useCallback } from 'react';
Ardından, basit addItem fonksiyon bildirimini,
Fonksiyon İfadesi'ne dönüştürelim, useCallback için
ilk parametre olarak fonksiyonumuzu bir geri çağırma işlevi olarak belirtelim.
İkinci parametre olarak köşeli parantezler içinde bağımlılıkları belirtelim -
fonksiyonda yer alan tüm reaktif değişkenleri, bizim durumumuzda
bu items dizisidir:
const addItem = useCallback(() => {
setItems(() => [...items, 'Yeni öğe']);
}, [items]);
İşte bu kadar! Böylece fonksiyonu önbelleğe aldık.
Butonlara tekrar tıklayalım ve
'tıkla' butonuna tıklandığında artık alt bileşenimizin
yeniden render edilmediğini görelim.
Bir App bileşeni oluşturun, içine
metin içeren bir paragraf yerleştirin.
Başlangıç değeri 'metin' olan bir state tanımlayın
ve onu paragrafta gösterin.
Paragrafa tıklandığında, metnin sonuna
bir ünlem işareti eklenmesini sağlayın.
İçinde yeni bir ürün eklemek için bir buton bulunan
bir alt bileşen Products oluşturun.
Onu App içinde yerleştirin.
Üst bileşende, bir ürün dizisi için bir state ve
yeni ürün ekleme fonksiyonu oluşturun.
Bunları prop olarak alt bileşene aktarın,
alt bileşende aktarılan diziyi bir ul listesi olarak gösterin.
Products içinde, konsola
'products render ediliyor' yazdırın.
Products'ı memo ile sarın.
Paragrafa ve butona tıklayın.
Paragrafa tıklandığında alt bileşenin
yine de yeniden render edildiğinden emin olun.
Ürün ekleme fonksiyonunu, onu useCallback kancası ile sararak önbelleğe alın.
Paragrafa ve butona tıklayın.
Paragrafa tıklandığında, alt bileşenin
artık yeniden render edilmediğinden emin olun.