19 Ocak 2021 Salı

React.memo ve useMemo nedir? Nasıl kullanılır?

  Ahmet Şimşek       19 Ocak 2021 Salı

React.memo nedir?

React.memo class componentlerde kullanılan shouldComponentUpdate ile aynı amaca hizmet eden bir higher-order componenttir. Componentin aldığı proplar üzerinden render edilmesini ya da hafızaya alınıp render edilmeden direkt hafızadan kullanılabilmesini sağlar. Bu da render süresi konusunda bir optimizasyon imkanı verir.

Aynı componentin birden fazla kez kullanıldığı durumda ya da bir component içerisindeki componentlerin yeniden render edilmesi gibi durumlarda componentin aldığı props değerlerine göre re-render durumunu tetikleyebilir ya da kesebiliriz.

Bir örnek üzerinden kullanımına göz atalım.

Aşağıdaki component iki farklı props değeri alıyor. Bu componentin birden fazla kullanıldığı durumda ve re-render tetikleyen bir olası durumda component her seferinde render olmak durumunda kalacak.

import React from 'react';

const Product = ({ name, price }) => {
return (
<div>
{name} {price}
</div>
)
}

export default Product;

Ancak bu aşamada componenti memo ile wrapleyerek eğer ilgili propslar değişirse render edilsin gibi bir hale çevirebiliriz. memo iki parametre ile çalışır.

1. parametre componentin kendisi, 2. parametre ise prevProps ve nextProps adında iki parametre alan bir fonksiyon. Bu fonksiyon class componentlerden tanıdğımız shouldComponentUpdate ile aynı mantıkta parametre alır. Ancak bu fonksiyon shouldComponentUpdate fonksiyonunun tam tersi gibi davranır. Yani eğer componentin render olmamasını hafızadaki halinin geri döndürülmesini istiyorsak true, tekrar render olmasını istiyorsak false değerini döndürüyoruz. false değerini döndüreceğimiz durumlar aldığı props değerlerinin değiştiği durumlar.
 
import React, { memo } from 'react';

const Product = ({ name, price }) => {
return (
<div>
{name} {price}
</div>
)
}

export default memo(Product, (prevProps, nextProps) => {
if (
prevProps.name !== nextProps.name
|| prevProps.price !== nextProps.price
) {
return false;
}
return true;
});

useMemo nedir?

useMemo tıpkı memo gibi hook her render anında çalışması gereken işlevleri hafızaya almayı ve aldığı ikinci parametrede verilen değerler üzerinden bir işlevi tekrar çağırmayı ya da hafızadaki değeri kullanabilmeyi sağlar. Bu da tıpkı memo gibi bir performans optimizasyonu imkanı sunar.

Örneğin bir array içerisinde filter ve map kullanmak durumunda kaldığımız bir örnek üzerinden gidelim.

Bir örnek üzerinden kullanımına göz atalım.

Aşağıdaki gibi verilen sayı kadar bi sayı listesi oluşturan ve listenin her elemanınıda checkbox ile seçebileceğimiz bir örnek üzerinden gidelim. Bu örnekte checkedNumbers statei checkbox a her tıklanıldığında değişecek. Bu durumda da getArray işlevi her seferinde çağrılacak. Ve konsolda koşan adam emojisini her seferinde görüyor olacağız.

import React, { useState } from "react";

const NumberListGenerator = () => {
const [number, setNumber] = useState(0);
const [checkedNumbers, setCheckedNumbers] = useState([]);

const getArray = () => {
console.log("🏃");
return Array(number)
.fill()
.map((_, i) => i);
};

const handleCheckboxChange = (event) => {
const valueNumber = parseInt(event.target.value, 10);

if (event.target.checked) {
setCheckedNumbers([...checkedNumbers, valueNumber]);
} else {
setCheckedNumbers(
checkedNumbers.filter((number) => number !== valueNumber)
);
}
};

return (
<div>
<input
value={number}
type="number"
onInput={(e) => setNumber(parseInt(e.target.value, 10))}
/>
<ul>
{getArray().map((number) => (
<li
key={number}
style={{
backgroundColor: checkedNumbers.includes(number) ? "#ccc" : "#fff"
}}
>
<input
value={number}
onChange={handleCheckboxChange}
type="checkbox"
/>
{number}
</li>
))}
</ul>
</div>
);
};

export default NumberListGenerator;

Bu olmasını istemediğimiz bi durum. Çünkü getArray fonksiyonunun sadece number statei değiştiği durumda tekrar çalışması gerek. Aşağıdaki şekilde bir değişiklik ile useMemonun ilk parametresinde fonksiyonu çağırıp ikinci parametresinde değişiminin takip edileceğiz state ya da props değerlerini yazarsak olası diğer tüm state ve props değişimlerinde bu fonksiyonun tekrar çalışmasının önüne geçmiş olacağız. Yani koşan adam emojisi sadece number değeri değiştiğinde log olarak düşmüş olacak.

import React, { useState, useMemo } from "react";

const NumberListGenerator = () => {
const [number, setNumber] = useState(0);
const [checkedNumbers, setCheckedNumbers] = useState([]);

const array = useMemo(() => {
console.log("🏃");
return Array(number)
.fill()
.map((_, i) => i);
}, [number]);

const handleCheckboxChange = (event) => {
const valueNumber = parseInt(event.target.value, 10);

if (event.target.checked) {
setCheckedNumbers([...checkedNumbers, valueNumber]);
} else {
setCheckedNumbers(
checkedNumbers.filter((number) => number !== valueNumber)
);
}
};

return (
<div>
<input
value={number}
type="number"
onInput={(e) => setNumber(parseInt(e.target.value, 10))}
/>
<ul>
{array.map((number) => (
<li
key={number}
style={{
backgroundColor: checkedNumbers.includes(number) ? "#ccc" : "#fff"
}}
>
<input
value={number}
onChange={handleCheckboxChange}
type="checkbox"
/>
{number}
</li>
))}
</ul>
</div>
);
};

export default NumberListGenerator;

Bu yazıda React.memo ve useMemonun ne olduğundan ve nasıl kullanılabileceğinden kısaca bahsettik. Bu işlevlerin dokümanında da yazdığı gibi kullanımları sadece performans optimizasyonu durumlarında öneriliyor. Bi işlevin çalışmasını engellemek ya da bir componentin render olmamasını sağlamak gibi durumlarda bu işlevlere güvenilmemesi gerektiği dokümanda belirtiliyor. Yani uygulamanızda daha performanslı çalışmasını istediğiniz bir alan varsa öncesinde performans iyileştirmesi için yapılabilecek şeyleri analiz ederek çalışma yapmak daha olumlu olacaktır.

Bu analizi neyle nasıl yapabilirim kısmında React Developer Tools eklentisi oldukça işinizi görebilir. Sonraki yazıda bu eklenti üzerine kısa bir örnek eklemeyi düşünüyorum. Sonraki yazıda görüşmek üzere.
logoblog

Thanks for reading React.memo ve useMemo nedir? Nasıl kullanılır?

Previous
« Prev Post

Hiç yorum yok:

Yorum Gönder