Hook optimalizácie výkonu useCallback v Reacte
V tejto lekcii sa pozrieme na nasledujúci
hook pre optimalizáciu výkonu
useCallback.
Hook useCallback je podobný API useMemo,
rozdiel je v tom, že prvý
ukladá do vyrovnávacej pamäte hodnotu medzi momentami prekreslenia
obrazovky, a druhý - callback.
To nám umožňuje nespúšťať náročné
funkcie, keď to nie je potrebné a môže
byť použité pri
odovzdávaní funkcie
do podriadených komponentov.
Poďme si to podrobnejšie rozobrať na príklade.
Na začiatok vytvorme komponent App
a vytvorme v ňom stav num:
const [num, setNum] = useState(0);
Nech máme tlačidlo, po kliknutí
na ktoré sa num zvyšuje
o 1, a odsek, v ktorom
budeme vypisovať hodnotu num:
return (
<div>
<button onClick={() => setNum(num + 1)}>klik</button>
<p>kliky: {num}</p>
</div>
);
A teraz, predpokladajme, že v
App sa vypisuje ešte nejaký zoznam
s prvkami, ktorý budeme dopĺňať
stlačením iného tlačidla. Pre ukladanie
prvkov tohto zoznamu vytvorme
stav items:
const [items, setItems] = useState([]);
A potom napíšme funkciu addItem
pre ich pridávanie:
function addItem() {
setItems([...items, 'nová položka']);
}
Teraz napíšme kód pre zobrazenie
prvkov zoznamu a presuňme ho do podriadeného
komponentu Items, ktorý vo forme
propov bude dostávať pole prvkov
a funkciu pre ich pridávanie. Nezabudnime
pridať výstup do konzoly, aby sme videli
kedy sa náš Items bude
prekresľovať:
function Items({ items, addItem }) {
const result = items.map((item, index) => {
return <p key={index}>{item}</p>;
});
console.log('Items render');
return (
<div>
<h3>Naše položky</h3>
{result}
<button onClick={addItem}>pridať položku</button>
</div>
);
}
export default Items;
Umiestnime Items na konci komponentu
App a budeme mu odovzdávať pole
items a funkciu pre pridávanie
prvkov addItem:
return (
<>
<div>
<button onClick={() => setNum(num + 1)}>klik</button>
<p>kliky: {num}</p>
<br />
</div>
<Items items={items} addItem={addItem} />
</>
);
A teraz klikajme na tlačidlá
a presvedčme sa, že num rastie a
nové prvky sa pridávajú do zoznamu.
A otvorením konzoly uvidíme, že
náš zoznam sa prekresľuje zakaždým,
aj keď klikáme na tlačidlo,
ktoré zvyšuje num.
Ak máme malý zoznam, tak je všetko
v poriadku, ale ak sa predpokladá, že
bude objemný a je v ňom ešte veľa iného?
Žiaden problém - poviete si, veď na minulej
lekcii sme prešli API memo,
aby sme sa vyhli zbytočným prekresleniam
komponentu.
Takže obaľme náš komponent
Items do memo a hotovo.
Mimochodom to je možné urobiť priamo
pri exporte Items:
export default memo(Items);
Nezabudnime importovať memo:
import { memo } from 'react';
A teraz otvorme konzolu a klikajme
na tlačidlá. Všetko nám vyšlo nazmar! My
sme memoizovali komponent, ale pri stlačení
tlačidla 'klik' sa komponent
Items aj tak
prekresľuje zakaždým.
Vec sa má tak, že keď sa nadradený
komponent prekreslí, jeho funkcie
sa znova vytvoria - to sa týka aj našej
funkcie addItem, ktorú odovzdávame do
Items.
Práve v tomto momente nám pomôže hook
useCallback. Poďme ho použiť.
Na začiatok ho importujme do
App:
import { useCallback } from 'react';
Potom prepracujme jednoduché deklaráciu funkcie
addItem na
Function Expression, určme ako
prvý parameter pre useCallback
našu funkciu vo forme callbacku. Druhým
parametrom v hranatých zátvorkách určme
závislosti - všetky reaktívne premenné,
zúčastňujúce sa vo funkcii, v našom prípade
je to pole items:
const addItem = useCallback(() => {
setItems(() => [...items, 'Nová položka']);
}, [items]);
Hotovo! Týmto sme funkciu uložili do vyrovnávacej pamäte.
Klikajme znova na tlačidlá a
vidíme, že teraz pri stlačení tlačidla
'klik' sa náš podriadený komponent neprekresľuje.
Vytvorte komponent App, umiestnite
do neho odsek s textom. Vytvorte
stav s počiatočnou hodnotou 'text'
a vypíšte ho v odseku. Nech po kliknutí
na odsek sa mu na koniec textu
pridá výkričník.
Vytvorte podriadený komponent Products,
v ktorom budete mať tlačidlo pre pridanie
nového produktu. Umiestnite ho v App.
V nadradenom komponente vytvorte stav
s poľom produktov a funkciu pridania
nového produktu. Odovzdajte ich
ako propy do podriadeného, vypíšte v ňom
odovzdané pole vo forme zoznamu ul.
V Products vypíšte do konzoly text
'products render'.
Obalte Products do memo.
Klikajte na odsek a tlačidlo. Presvedčte sa,
že pri kliknutí na odsek sa podriadený komponent
aj tak prekresľuje.
Uložte do vyrovnávacej pamäte funkciu pre pridanie
produktov, obalením jej do hooku useCallback.
Klikajte na odsek a tlačidlo. Presvedčte sa,
že pri kliknutí na odsek sa podriadený komponent
už neprekresľuje.