⊗jsrtPmHkUCb 16 of 47 menu

Hook optymalizacji wydajności useCallback w React

W tej lekcji przyjrzymy się następującemu hookowi do optymalizacji wydajności useCallback.

Hook useCallback jest podobny do API useMemo, różnica polega na tym, że pierwszy przechowuje w pamięci podręcznej wartość między momentami przerysowania ekranu, a drugi - funkcję zwrotną (callback). Pozwala nam to nie uruchamiać ponownie wymagających zasobów funkcji, gdy nie jest to wymagane i może być używane przy przekazywaniu funkcji do komponentów potomnych.

Przyjrzyjmy się temu dokładniej na przykładzie. Na początek utwórzmy komponent App i utwórzmy w nim stan num:

const [num, setNum] = useState(0);

Niech będzie przycisk, po kliknięciu którego num zwiększa się o 1, oraz akapit, w którym będziemy wyświetlać wartość num:

return ( <div> <button onClick={() => setNum(num + 1)}>kliknij</button> <p>kliknięcia: {num}</p> </div> );

A teraz załóżmy, że w App wyświetla się jeszcze jakaś lista z elementami, którą będziemy uzupełniać po naciśnięciu innego przycisku. Do przechowywania elementów tej listy utwórzmy stan items:

const [items, setItems] = useState([]);

A następnie napiszmy funkcję addItem do ich dodawania:

function addItem() { setItems([...items, 'nowy element']); }

Teraz napiszmy kod do wyświetlania elementów listy i przenieśmy go do komponentu potomnego Items, który w postaci propsów będzie otrzymywać tablicę elementów i funkcję do ich dodawania. Nie zapomnijmy dodać wyjścia do konsoli, aby widzieć kiedy nasz Items będzie przerysowywany:

function Items({ items, addItem }) { const result = items.map((item, index) => { return <p key={index}>{item}</p>; }); console.log('Renderowanie Items'); return ( <div> <h3>Nasze elementy</h3> {result} <button onClick={addItem}>dodaj element</button> </div> ); } export default Items;

Umieśćmy Items na końcu komponentu App i przekazujmy mu tablicę items i funkcję do dodawania elementów addItem:

return ( <> <div> <button onClick={() => setNum(num + 1)}>kliknij</button> <p>kliknięcia: {num}</p> <br /> </div> <Items items={items} addItem={addItem} /> </> );

A teraz ponaciśnijmy na przyciski i przekonajmy się, że num rośnie i nowe elementy dodają się do listy. A otwierając konsolę, zobaczymy, że nasza lista przerysowuje się za każdym razem, nawet jeśli klikamy na przycisk, który zwiększa num.

Jeśli mamy małą listę, to wszystko w porządku, a jeśli zakłada się, że będzie obszerna i jest tam jeszcze wiele innych rzeczy? Nie problem - powiesz, przecież na poprzedniej lekcji poznaliśmy API memo, żeby właśnie unikać niepotrzebnych przerysowań komponentu.

Więc zawińmy nasz komponent Items w memo i po sprawie. Nawiasem mówiąc, można to zrobić bezpośrednio przy eksporcie Items:

export default memo(Items);

Nie zapomnijmy zaimportować memo:

import { memo } from 'react';

A teraz otwórzmy konsolę i ponaciśnijmy na przyciski. Wszystkie starania na marne! My zmemowaliśmy komponent, ale po naciśnięciu na przycisk 'kliknij' komponent Items i tak przerysowuje się za każdym razem.

Chodzi o to, że kiedy komponent rodzica jest przerysowywany, jego funkcje są ponownie tworzone - dotyczy to również naszej funkcji addItem, którą przekazujemy do Items.

Właśnie w tym momencie pomoże nam hook useCallback. Zastosujmy go. Na początek zaimportujmy go do App:

import { useCallback } from 'react';

Następnie przeróbmy proste zadeklarowanie funkcji addItem na Wyrażenie funkcyjne, wskażmy jako pierwszy parametr dla useCallback naszą funkcję w postaci callbacka. Drugim parametrem w nawiasach kwadratowych wskażmy zależności - wszystkie reaktywne zmienne, uczestniczące w funkcji, w naszym przypadku to tablica items:

const addItem = useCallback(() => { setItems(() => [...items, 'Nowy element']); }, [items]);

Gotowe! W ten sposób zapisaliśmy w pamięci podręcznej funkcję. Naciskamy ponownie na przyciski i widzimy, że teraz po naciśnięciu na przycisk 'kliknij' nasz komponent potomny nie przerysowuje się.

Utwórz komponent App, umieść w nim akapit z tekstem. Utwórz stan z wartością początkową 'tekst' i wyświetl go w akapicie. Niech po kliknięciu na akapit na końcu tekstu dodaje się wykrzyknik.

Utwórz komponent potomny Products, w którym będzie przycisk do dodawania nowego produktu. Umieść go w App. W komponencie rodzica utwórz stan z tablicą produktów i funkcję dodawania nowego produktu. Przekaż je jako propsy do komponentu potomnego, wyświetl w nim przekazaną tablicę w postaci listy ul.

W Products wyświetl w konsoli tekst 'renderowanie produktów'. Zawiń Products w memo. Klikaj na akapit i przycisk. Upewnij się, że po kliknięciu na akapit komponent potomny i tak się przerysowuje.

Zapisz w pamięci podręcznej funkcję do dodawania produktów, zawijając ją w hook useCallback. Klikaj na akapit i przycisk. Upewnij się, że po kliknięciu na akapit, komponent potomny już się nie przerysowuje.

Polski
AfrikaansAzərbaycanБългарскиবাংলাБеларускаяČeštinaDanskDeutschΕλληνικάEnglishEspañolEestiSuomiFrançaisहिन्दीMagyarՀայերենIndonesiaItaliano日本語ქართულიҚазақ한국어КыргызчаLietuviųLatviešuМакедонскиMelayuမြန်မာNederlandsNorskPortuguêsRomânăРусскийසිංහලSlovenčinaSlovenščinaShqipСрпскиSrpskiSvenskaKiswahiliТоҷикӣไทยTürkmenTürkçeЎзбекOʻzbekTiếng Việt
Wykorzystujemy pliki cookie do działania strony, analizy i personalizacji. Przetwarzanie danych odbywa się zgodnie z Polityką prywatności.
zaakceptuj wszystkie dostosuj odrzuć