Memoization, önbelleğe almaya benzer bir optimizasyon tekniğidir. Bir işlev çağrısının önceki sonuçlarını saklayarak ve işlevin bir sonraki çalışmasında bu sonuçları kullanarak çalışır. Aynı parametreler üzerinde işlev çağrılarını tekrarlayan hesaplama ağırlıklı uygulamalarda özellikle kullanışlıdır.
Notlamayı düz JavaScript’te ve ayrıca React’te birkaç farklı şekilde kullanabilirsiniz.
JavaScript’te not alma
JavaScript’te bir işlevi hafızaya almak için, o işlevin sonuçlarını bir önbellekte saklamanız gerekir. Önbellek, bağımsız değişkenleri anahtar ve sonuçları değer olarak içeren bir nesne olabilir.
Bu işlevi çağırdığınızda, çalıştırmadan önce sonucun önbellekte var olup olmadığını kontrol eder. Öyleyse, önbelleğe alınan sonuçları döndürür. Aksi takdirde yürütür.
Bu işlevi göz önünde bulundurun:
function square(num) {
return num * num
}
İşlev bir argüman alır ve karesini döndürür.
İşlevi çalıştırmak için şunun gibi bir numarayla arayın:
square(5) // 25
Argüman olarak 5 ile square() oldukça hızlı çalışacaktır. Ancak, 70.000’in karesini hesaplarsanız, gözle görülür bir gecikme olacaktır. Fazla değil ama yine de bir gecikme. Şimdi, işlevi birden çok kez çağırırsanız ve 70.000’i geçerseniz, her aramada bir gecikme yaşarsınız.
Not almayı kullanarak bu gecikmeyi ortadan kaldırabilirsiniz.
const memoizedSquare = () => {
let cache = {};
return (num) => {
if (num in cache) {
console.log(‘Reusing cached value’);
return cache[num];
} else {
console.log(‘Calculating result’);
let result = num * num;
// cache the new result value for next time
cache[num] = result;
return result;
}
}
}
Bu örnekte işlev, önbellek nesnesinde var olup olmadığını kontrol ederek sonucun daha önce hesaplanıp hesaplanmadığını kontrol eder. Varsa, önceden hesaplanmış değeri döndürür.
İşlev yeni bir sayı aldığında, yeni bir değer hesaplar ve sonuçları dönmeden önce önbellekte saklar.
Yine bu örnek oldukça basittir, ancak not almanın bir programın performansını iyileştirmek için nasıl çalışacağını açıklar.
Yalnızca saf işlevleri ezberlemelisiniz. Bu işlevler, aynı bağımsız değişkenleri ilettiğinizde aynı sonucu verir. Saf olmayan işlevlerde memoization kullanırsanız, performansı iyileştirmezsiniz, ancak ek yükü artırırsınız. Bunun nedeni, bir işlevi her ezberlediğinizde hafıza yerine hızı seçmenizdir.
React’te Notlandırma
React bileşenlerini optimize etmek istiyorsanız React, useMemo() kancası, React.memo ve useCallBack() aracılığıyla notlandırma sağlar.
useMemo() işlevini kullanma
useMemo(), bir işlevi ve bir bağımlılık dizisini kabul eden bir React kancasıdır.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
Bu fonksiyondan dönen değeri hafızaya alır. Bağımlılık dizisindeki değerler, işlev yürütüldüğünde dikte eder. Yalnızca değiştiklerinde işlev yeniden yürütülür.
Örneğin, aşağıdaki Uygulama bileşeninin sonuç adı verilen hafızaya alınmış bir değeri vardır.
import { useMemo } from “react”
function App(value) {
const square = (value) => {
return value * value
}
const result = useMemo(
() => square(value),
[ value ]
);
return (
<div>{result(5)}</div>
)
}
App bileşeni, her işlemede square() öğesini çağırır. Uygulama bileşeni , özellikle square() işlevi pahalıysa, React donanımlarının değiştirilmesi veya durum güncellemesi nedeniyle birçok kez işlenirse performans düşecektir .
Ancak, useMemo() döndürülen değerleri önbelleğe aldığından, bağımlılık dizisindeki bağımsız değişkenler değişmedikçe kare işlevi her yeniden işlemede yürütülmez.
React.memo()’yu kullanma
React.memo(), bir React bileşenini ve bir işlevi bağımsız değişken olarak kabul eden daha yüksek dereceli bir bileşendir. İşlev, bileşenin ne zaman güncellenmesi gerektiğini belirler.
İşlev isteğe bağlıdır ve sağlanmadığı takdirde React.memo, bileşenin mevcut donanımlarının önceki donanımlarıyla yüzeysel bir kopya karşılaştırması yapar. Sahne donanımı farklıysa, bir güncellemeyi tetikler. Donanımlar aynıysa, yeniden işlemeyi atlar ve hafızaya alınan değerleri yeniden kullanır.
İsteğe bağlı işlev, önceki donanımları ve sonraki donanımları bağımsız değişken olarak kabul eder. Daha sonra, bileşenin güncellenip güncellenmeyeceğine karar vermek için bu donanımları açık bir şekilde karşılaştırabilirsiniz.
React.memo(Component, [areEqual(prevProps, nextProps)])
Önce isteğe bağlı işlev bağımsız değişkeni olmayan bir örneğe bakalım. Aşağıda, adı ve e-posta desteğini kabul eden Yorumlar adlı bir bileşen bulunmaktadır.
function Comments ({name, comment, likes}) {
return (
<div>
<p>{name}</p>
<p>{comment}</p>
<p>{likes}</p>
</div>
)
}
Notlandırılmış yorumlar bileşeni, React.memo’yu şu şekilde saracaktır:
const MemoizedComment = React.memo(Comment)
Diğer herhangi bir React bileşeni gibi arayabilir ve arayabilirsiniz.
<MemoizedComment name=”Mary” comment=”Memoization is great” likes=1/>
Donanım karşılaştırmasını kendiniz yapmak istiyorsanız, aşağıdaki işlevi ikinci argüman olarak React.memo’ya iletin.
import React from “react”
function checkCommentProps(prevProps, nextProps) {
return prevProps.name === nextProps.name
&& prevProps.comment === nextProps.comment
&& prevProps.likes === nextProps.likes
}
const MemoizedComment = React.memo(Comments, checkCommentProps)
checkProfileProps true değerini döndürürse, bileşen güncellenmez. Aksi takdirde yeniden işlenir.
Özel işlev, yeniden işlemeyi özelleştirmek istediğinizde kullanışlıdır. Örneğin, Yorumlar bileşenini yalnızca beğeni sayısı değiştiğinde güncellemek için kullanabilirsiniz.
Bir işlevin yalnızca döndürülen değerini ezberleyen useMemo() kancasının aksine, React.memo tüm işlevi ezberler.
React.memo’yu yalnızca saf bileşenler için kullanın. Ayrıca, karşılaştırma maliyetlerini azaltmak için yalnızca donanımları sıklıkla değişen bileşenleri not edin.
useCallBack() işlevini kullanma
İşlev bileşenlerini not almak için useCallBack() kancasını kullanabilirsiniz .
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
İşlev, yalnızca bağımlılık dizisindeki değerler değiştiğinde güncellenir. Kanca, useMemo() geri araması gibi çalışır, ancak değerleri ezberlemek yerine, işlev bileşenini işlemeler arasında ezberler.
Bir API’yi çağıran, not edilmiş bir işlevin aşağıdaki örneğini ele alalım.
import { useCallback, useEffect } from “react”;
const Component = () => {
const getData = useCallback(() => {
console.log(‘call an API’);
}, []);
useEffect(() => {
getData();
}, [getData]);
};
useEffect’te çağrılan getData() işlevi, yalnızca getData değeri değiştiğinde tekrar çağrılacaktır.
Not Almalı Mısın?
Bu öğreticide, memoizasyonun ne olduğunu, faydalarını ve JavaScript ile React’te nasıl uygulanacağını öğrendiniz. Ancak, React’in zaten hızlı olduğunu bilmelisiniz. Çoğu durumda, bileşenleri veya değerleri not almak karşılaştırma maliyetlerini artırır ve performansı artırmaz. Bu nedenle, yalnızca pahalı bileşenleri ezberleyin.
React 18 ayrıca useId, useTransition ve useInsertionEffect gibi yeni kancaları da tanıttı. Bunları, React uygulamalarının performansını ve kullanıcı deneyimini geliştirmek için kullanabilirsiniz.