Zapamiętywanie to technika optymalizacji, podobna do pamięci podręcznej. Działa poprzez przechowywanie poprzednich wyników wywołania funkcji i wykorzystanie tych wyników przy następnym uruchomieniu funkcji. Jest to szczególnie przydatne w aplikacjach z dużą ilością obliczeń, które powtarzają wywołania funkcji na tych samych parametrach.

Możesz używać memoization w zwykłym JavaScript, a także w React na kilka różnych sposobów.

Zapamiętywanie w JavaScript

Aby zapamiętać funkcję w JavaScript, musisz przechowywać wyniki tej funkcji w pamięci podręcznej. Pamięć podręczna może być obiektem z argumentami jako kluczami i wynikami jako wartościami.

Po wywołaniu tej funkcji najpierw sprawdza, czy wynik znajduje się w pamięci podręcznej przed uruchomieniem. Jeśli tak, zwraca wyniki z pamięci podręcznej. W przeciwnym razie wykonuje.

Rozważ tę funkcję:

funkcjonowaćkwadrat(liczba) {
zwrócić liczba * liczba
}

Funkcja przyjmuje argument i zwraca jego kwadrat.

Aby uruchomić funkcję, wywołaj ją takim numerem:

kwadrat(5) // 25
instagram viewer

Z 5 jako argumentem, square() będzie działać dość szybko. Jeśli jednak obliczysz kwadrat 70 000, będzie zauważalne opóźnienie. Niewiele, ale jednak z opóźnieniem. Teraz, gdybyś wywołał funkcję wiele razy i przekazał 70 000, doświadczyłbyś opóźnienia w każdym wywołaniu.

Możesz wyeliminować to opóźnienie za pomocą zapamiętywania.

stały memoizedSquare = () => {
wynajmować Pamięć podręczna = {};
zwrócić (liczba) => {
jeśli (liczba w Pamięć podręczna) {
konsola.log('Ponowne wykorzystanie wartości z pamięci podręcznej');
zwrócić Pamięć podręczna[liczba];
} w przeciwnym razie {
konsola.log('Obliczanie wyniku');
wynajmować wynik = liczba * liczba;

// Pamięć podręczna ten Nowywynikwartośćdlanastępnyczas
Pamięć podręczna[liczba] = wynik;
zwrócić wynik;
}
}
}

W tym przykładzie funkcja sprawdza, czy wcześniej obliczyła wynik, sprawdzając, czy istnieje on w obiekcie pamięci podręcznej. Jeśli tak, zwraca już obliczoną wartość.

Gdy funkcja otrzymuje nową liczbę, oblicza nową wartość i przechowuje wyniki w pamięci podręcznej, zanim zwróci.

Ten przykład jest dość prosty, ale wyjaśnia, jak działa zapamiętywanie, aby poprawić wydajność programu.

Powinieneś zapamiętywać tylko czyste funkcje. Te funkcje zwracają ten sam wynik, gdy przekazujesz te same argumenty. Jeśli używasz zapamiętywania na nieczystych funkcjach, nie poprawisz wydajności, ale zwiększysz koszty. Dzieje się tak, ponieważ za każdym razem, gdy zapamiętujesz funkcję, wybierasz szybkość, a nie pamięć.

Zapamiętywanie w React

Jeśli chcesz zoptymalizować komponenty Reacta, React zapewnia memoization poprzez hook useMemo(), React.memo i useCallBack().

Korzystanie z funkcji useMemo()

useMemo() to Reaguj hak który akceptuje funkcję i tablicę zależności.

stały memoizedValue = useMemo(() => computeExpensiveValue (a, b), [a, b]);

Zapamiętuje wartość zwróconą z tej funkcji. Wartości w tablicy zależności określają, kiedy funkcja jest wykonywana. Dopiero po ich zmianie funkcja jest ponownie wykonywana.

Na przykład następujący składnik aplikacji ma zapamiętaną wartość o nazwie wynik.

import { użyjNotatki } z "reagować"
funkcjonowaćAplikacja(wartość) {
stały kwadrat = (wartość) => {
zwrócić wartość * wartość
}
stały wynik = użyjMemo(
() => kwadrat (wartość),
[ wartość ]
);
zwrócić (
<div>{wynik (5)}</div>
)
}

Komponent App wywołuje square() przy każdym renderowaniu. Wydajność ulegnie pogorszeniu, jeśli składnik aplikacji będzie renderowany wiele razy z powodu Reaguj rekwizyty zmiana lub aktualizacja stanu, zwłaszcza jeśli funkcja square() jest droga.

Jednak ponieważ useMemo() buforuje zwrócone wartości, funkcja square nie jest wykonywana przy każdym ponownym renderowaniu, chyba że zmienią się argumenty w tablicy zależności.

Korzystanie z React.memo()

React.memo() to komponent wyższego rzędu, który akceptuje komponent React i funkcję jako argumenty. Funkcja określa, kiedy składnik powinien zostać zaktualizowany.

Funkcja jest opcjonalna i jeśli nie jest podana, React.memo wykonuje płytkie porównanie aktualnych właściwości komponentu z jego poprzednimi właściwościami. Jeśli rekwizyty są różne, uruchamia aktualizację. Jeśli właściwości są takie same, pomija ponowne renderowanie i ponownie wykorzystuje zapamiętane wartości.

Funkcja opcjonalna przyjmuje jako argumenty poprzednie właściwości i następne właściwości. Następnie możesz jawnie porównać te właściwości, aby zdecydować, czy zaktualizować komponent, czy nie.

Reagować.notatka(Składnik, [areEqual (prevProps, nextProps)])

Spójrzmy najpierw na przykład bez opcjonalnego argumentu funkcji. Poniżej znajduje się komponent o nazwie Komentarze, który akceptuje właściwości nazwy i adresu e-mail.

funkcjonowaćUwagi ({imię, komentarz, polubienia}) {
zwrócić (
<div>
<p>{Nazwa}</p>
<p>{komentarz}</p>
<p>{lubi}</p>
</div>
)
}

Zapamiętany komponent komentarzy będzie miał React.memo owinięty wokół niego w następujący sposób:

stały MemoizedComment = React.memo (Komentarz)

Możesz wywołać, a następnie wywołać jak każdy inny komponent React.

<Zapamiętany komentarz nazwa="Mary" komentarz="Zapamiętywanie jest świetne" polubienia=1/>

Jeśli chcesz samodzielnie przeprowadzić porównanie właściwości, przekaż poniższą funkcję do React.memo jako drugi argument.

import Reagować z "reagować"
funkcjonowaćsprawdźKomentarzRekwizyty(prevProps, nextProps) {
zwrócić prevProps.name nextProps.name
&& prevProps.comment nextProps.comment
&& prevProps.likes następneProps.likes
}

stały MemoizedComment = React.memo (Komentarze, checkCommentProps)

Jeśli checkProfileProps zwraca true, komponent nie jest aktualizowany. W przeciwnym razie jest ponownie renderowany.

Funkcja niestandardowa jest przydatna, gdy chcesz dostosować ponowne renderowanie. Na przykład możesz go użyć do aktualizacji komponentu Komentarze tylko wtedy, gdy zmieni się liczba polubień.

W przeciwieństwie do hooka useMemo(), który zapamiętuje tylko zwróconą wartość funkcji, React.memo zapamiętuje całą funkcję.

Używaj React.memo tylko do czystych komponentów. Ponadto, aby zmniejszyć koszty porównań, zapamiętuj tylko te elementy, których rekwizyty często się zmieniają.

Korzystanie z funkcji useCallBack()

Możesz użyć haka useCallBack() do zapamiętywania elementy funkcyjne.

stały memoizedCallback = useCallback(
() => {
zrobić coś (a, b);
},
[a, b],
);

Funkcja jest aktualizowana tylko wtedy, gdy zmieniają się wartości w tablicy zależności. Podpięcie działa jak wywołanie zwrotne useMemo(), ale zapamiętuje komponent funkcji między renderowaniami zamiast zapamiętywania wartości.

Rozważmy następujący przykład zapamiętanej funkcji, która wywołuje interfejs API.

import { useCallback, useEffect } z "reagować";
stały Składnik = () => {
stały getData = useCallback(() => {
konsola.log('wywołać API');
}, []);
useEffect(() => {
otrzymać dane();
}, [otrzymać dane]);
};

Funkcja getData() wywołana w useEffect zostanie wywołana ponownie tylko wtedy, gdy zmieni się wartość getData.

Czy powinieneś zapamiętać?

W tym samouczku dowiedziałeś się, czym jest zapamiętywanie, jakie daje korzyści oraz jak zaimplementować ją w JavaScript i React. Powinieneś jednak wiedzieć, że React jest już szybki. W większości przypadków zapamiętywanie składników lub wartości zwiększa koszty porównania i nie poprawia wydajności. Z tego powodu zapamiętuj tylko drogie komponenty.

React 18 wprowadził również nowe haki, takie jak useId, useTransition i useInsertionEffect. Możesz ich użyć do poprawy wydajności i doświadczenia użytkownika aplikacji React.