6. diel - Hooky v React - useCallback() a useMemo()
V predchádzajúcej lekcii, Základy štylovania aplikácie pomocou Material UI v Reactu , sme sa dozvedeli, ako pridať
aplikáciu v React štýly pomocou knižnice Material UI a zoznámili sme sa s
komponentmi Container
, Grid
, Typography
a
Button
.
V tomto tutoriále pokročilého Reactu budeme pokračovať
v téme hookov. Pozrieme sa na dva hooky slúžiace na cachovanie
dát medzi renderovaním v React aplikácii. Konkrétne to budú hooky
useCallback()
a useMemo()
.
Hook useCallback()
Tento hook slúži na optimalizáciu výkonu komponentov.
Umožňuje vytvoriť a uchovať v pamäti referenciu na funkciu
tak, aby sa táto funkcia znovu vytvárala iba keď sa zmení konkrétne
závislosti. React pri použití useCallback()
funkciu iba vracia,
nevolá ju. Hook je užitočný predovšetkým v situáciách, kde chceme
zabrániť zbytočnému vytváraniu nových funkcií pri každom vykreslení
komponentu.
Syntax hooku useCallback()
vyzerá takto:
Kód si popíšeme:
memoizedFunction
je do premennej uložená funkcia, ktorá bude memoizovaná a vrátená hookomuseCallback()
,- ako prvý argument hook prijíma funkciu, ktorá má byť memoizovaná,
- druhým argumentom je pole závislostí, ktoré obsahuje premenné, od ktorých závisí daná funkcia. Funkcia sa vytvorí znovu iba ak sa niektorá z týchto premenných zmení.
useCallback()
Typickou situáciou pre použitie useCallback()
je, keď
odovzdávame funkciu ako prop (vlastnosť) do komponentu, ktorý je
optimalizovaný pomocou funkcie memo()
. Pomocou memo()
zamedzujeme prekresľovaniu komponentu v prípade, že jej props zostávajú
rovnaké.
V JavaScripte však funkcia vždy vytvára novú funkciu. Preto funkcia
posúvaná pomocou props do komponentu bude pri každom renderovaní
považovaná za funkciu novú, aj keď sa nijako nezmení. Optimalizácia iba
pomocou memo()
v tomto prípade nebude fungovať, pokiaľ
posúvanú funkciu neobalíme hookom useCallback()
.
Najlepšie bude ukázať si to na konkrétnom príklade:)
Funkcia memo()
a hook useMemo sú dve odlišné
veci. Funkcia memo()
slúži na memoizáciu celého komponentu.
Hook useMemo()
slúži na memoizáciu výsledku výpočtu alebo
hodnoty v rámci komponentu.
Použitie useCallback()
v aplikácii
Budeme vychádzať z aplikácie z lekcie Hooky v React - useState(), useEffect() a useRef().
V nej si tiež stiahneme projekt, ktorý teraz spoločne upravíme. Výsledná aplikácia bude vyzerať takto:
Príprava projektu
Stiahnutý projekt si otvoríme v preferovanom editore kódu. V termináli si spustíme príkaz na inštaláciu modulov a projekt spustíme na lokálnom serveri:
Element input
už nebudeme potrebovať, preto v komponente MainCompChild.js
zmažeme premennú inputRef
a hook useEffect()
.
Zmažeme aj input
z vykresľovanej časti.
Potom pridáme novú funkcionalitu. Importujeme si rovno všetky hooky, ktoré využijeme:
Hneď pod
console.log
potom do funkcie MainCompChild()
vložíme
kód:
Vytvoríme stav, kde si
ukladáme číslo, od ktorého pomocou funkcie
decrementChildCount()
odčítame jednotku. Funkcia sa neskôr
spustí po kliknutí na tlačidlo.
V časti za return
potom pod nadpisom <h3>
vypíšeme aktuálny stav premennej childCount
:
Pridanie komponentu
Button
Teraz si do aplikácie pridáme vlastný komponent na vykreslenie tlačidla. Tento komponent bude prijímať ako prop funkciu, ktorá sa spustí po kliknutí na tlačidlo.
Vytvoríme si zložku UI/
v adresári src
av nej
súbor Button.js
s nasledujúcim kódom:
Po každom renderovaní tlačidla si vypíšeme do konzoly, že render
prebehol ao ktoré tlačidlo ide. Tlačidlo si exportujeme pomocou funkcie
memo()
. To nám zaistí, že sa prekreslí iba ak sa zmení jeho
prop.
Teraz tlačidlo použijeme v súbore MainCompChild.js
. Najprv si
ho importujeme:
Pod vykreslenie odseku
<p>
s počtom vložíme kód:
Aplikácia teraz vyzerá nasledovne:
Implementácia hooku
useCallback()
Naše tlačidlo je exportované pomocou funkcie memo()
.
Očakávame preto, že sa opätovne vykreslí iba vtedy, ak sa zmení jeho
props.
Keď si však otvoríme vývojárske nástroje, premažeme konzolu a klikneme
na tlačidlo Plus v hlavnom komponente alebo na tlačidlo
Mínus v detskom komponente, vidíme, že sa zakaždým znovu
vykresľuje tlačidlo s mínusom, ktoré je urobené cez náš vlastný
<Button>
komponent. V konzole vidíme pri každom vykreslení
tlačidla vypísaný nadpis tlacitko render -
.
Je to preto, že React opakovane pri každom rendere vytvára funkciu
decrementChildCount()
, ktorú tlačidlo v detskom komponente
prijíma ako prop. Preto sa tlačidlo aj napriek použitiu
memo()
opätovne vykresľuje.
To opravíme použitím hooku useCallback()
, do ktorého
obalíme funkciu decrementChildCount()
v súbore
MyCompChild.js
. Funkciu nahradíme kódom:
Pole závislostí je prázdne a funkcia preto zostáva zakaždým rovnaká. Keď sa teraz pozrieme do konzoly vo vývojárskych nástrojoch a klikneme na Plus alebo Mínus, vidíme, že tlačidlo s mínusom sa vykresľuje iba pri prvotnom renderovaní, potom už nie.
Hook useMemo()
Hook useMemo()
slúži na memoizáciu výpočtov a
hodnôt, a tým pomáha optimalizovať výkon komponentov. Memoizácia
znamená uchovanie výsledku výpočtu a jeho opätovné použitie, pokiaľ sa
vstupná závislosť nezmení. Koncept už poznáme z hooku
useCallback()
. Len tentoraz neukladáme celú funkciu, ale iba jej
výsledok.
Syntax hooku vyzerá takto:
Pozrime sa na kód bližšie:
memoizedValue
je uložený výsledok výpočtu alebo transformácie dát, ktorý bude memoizovaný a vrátený hookomuseMemo()
,- ako prvý argument hook prijíma výpočet alebo transformáciu dát, ktorá má byť memoizovaná,
- ako druhý argument potom vložíme pole závislostí, ktoré obsahuje premenné, od ktorých závisí náš výpočet. Ak sa niektorá z týchto premenných zmení, výpočet sa vykoná znova. Inak sa vráti uložená hodnota z predošlého renderovania.
useMemo()
Do hooku useMemo()
sa obvykle ukladajú náročné
kalkulácie, ktorých závislosti sa menia iba ojedinele. Inak platí
to, čo pre useCallback()
. Hook oceníme, pokiaľ je hodnota
posúvaná v prop komponente obalenej funkciou memo()
, alebo je
hodnota využitá ako závislosť iného hooku.
Poďme si teraz ukázať konkrétny príklad použitia hooku
useMemo()
.
Použitie useMemo()
v
aplikácii
Budeme pokračovať v práci s našou aplikáciou. Otvoríme si súbor
MainCompChild.js
. Pod funkciu decrementChildCount()
vložíme novú funkciu, ktorú potom rovno zavoláme pre
childCount
a výsledok uložíme do premennej
doubleWithoutMemo
:
Pod tlačidlo Mínus potom vypíšeme výsledok:
Otvoríme si vývojárske
nástroje. V konzole po kliknutí na tlačidlo Plus vidíme, že
prebehne výpočet zdvojnásobenia premennej childCount
av konzole
sa vypíše text krát dva
. To je však zbytočné, pretože sa
táto premenná nemení.
Pomocou hooku useMemo()
teraz docielime, nech sa výpočet
opakovane vykonal iba pri zmene stavu childCount
, teda po kliknutí
na tlačidlo Mínus. Premennú doubleWithoutMemo
nahradím
kódom:
A k Počet krát dva
vykreslíme hodnotu premennej memoizedVal
:
Teraz sme v situácii, že je naša funkcia countDouble()
závislosťou hooku useMemo()
. Pre správnu funkcionalitu ju preto
ešte zabalíme do hooku useCallback()
, nech sa závislosť hooku
useMemo()
nemení pri každom renderovaní.
Funkciu countDouble()
nahradíme kódom:
Hotovo:) V konzole
vývojárskych nástrojov teraz po kliknutí na Plus vidíme, že
výpočet zdvojnásobenia premennej childCount
už zbytočne
neprebieha. Dosiahli sme to vďaka využitiu kombinácie hookov
useCallback()
a useMemo()
.
V nasledujúcej lekcii, Načítanie dát na pozadí , si vyskúšame použitie komponentu
Suspense
v kombinácii s funkciou lazy()
. To nám
pomôže užívateľovi komunikovať, že dáta ešte nie sú všetky
načítané a pripravené na zobrazenie.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 8x (321.49 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript