A useCallback teljesítményoptimalizáló hook a React-ban
Ebben a leckében megvizsgáljuk a következő
teljesítményoptimalizáló hook-ot,
a useCallback-ot.
A useCallback hook hasonló a useMemo API-hoz,
a különbség az, hogy az első
egy visszahívó függvényt gyorsítótáraz a renderelések között,
míg a második egy értéket.
Ez lehetővé teszi számunkra, hogy ne indítsuk újra az erőforrás-igényes
függvényeket, amikor az nem szükséges, és
használható
függvény átadásakor
gyermek komponenseknek.
Nézzük meg részletesebben egy példán keresztül.
Először hozzunk létre egy App komponenst
és hozzunk létre benne egy num állapotot:
const [num, setNum] = useState(0);
Legyen egy gombunk, amelyre kattintáskor
a num értéke
1-gyel nő, és egy bekezdés, amelyben
kiírjuk a num értékét:
return (
<div>
<button onClick={() => setNum(num + 1)}>click</button>
<p>clicks: {num}</p>
</div>
);
Tegyük fel most, hogy a
App-ben még megjelenik egy lista
elemmel, amelyet egy másik gomb megnyomásával
fogunk bővíteni. Az elemek tárolásához
hozzunk létre egy
items állapotot:
const [items, setItems] = useState([]);
Majd írjunk egy addItem
függvényt a hozzáadásukhoz:
function addItem() {
setItems([...items, 'new item']);
}
Most írjuk meg a lista elemeinek megjelenítéséhez szükséges kódot
és helyezzük át egy gyermek komponensbe, a Items-be,
amely prop-ként kapja meg az elemek tömbjét
és a hozzáadásukra szolgáló függvényt. Ne felejtsük el
hozzáadni a konzolra történő kiírást, hogy lássuk,
mikor renderelődik újra a Items:
function Items({ items, addItem }) {
const result = items.map((item, index) => {
return <p key={index}>{item}</p>;
});
console.log('Items render');
return (
<div>
<h3>Our items</h3>
{result}
<button onClick={addItem}>add item</button>
</div>
);
}
export default Items;
Helyezzük el a Items-t a
App komponens végén, és adjuk át neki a
items tömböt és az elemek hozzáadására szolgáló
addItem függvényt:
return (
<>
<div>
<button onClick={() => setNum(num + 1)}>click</button>
<p>clicks: {num}</p>
<br />
</div>
<Items items={items} addItem={addItem} />
</>
);
Most kattintsunk a gombokra
és győződjünk meg róla, hogy a num nő és
új elemek kerülnek a listába.
És ha megnyitjuk a konzolt, látni fogjuk, hogy
a listánk minden alkalommal újrarajzolódik,
még akkor is, ha arra a gombra kattintunk,
amely növeli a num-ot.
Ha kis listánk van, akkor minden
rendben, de mi van, ha feltételezhető, hogy
terjedelmes lesz és sok minden más is van benne?
Nem gond - mondhatod, hiszen az előző
leckében megvizsgáltuk a memo API-t,
éppen azért, hogy elkerüljük a komponens szükségtelen újrarajzolásait.
Tehát csomagoljuk be a Items komponensünket
a memo-ba, és kész is.
Egyébént ezt megtehetjük közvetlenül
a Items exportálásakor:
export default memo(Items);
Ne felejtsük el importálni a memo-t:
import { memo } from 'react';
Most nyissuk meg a konzolt és kattintsunk
a gombokra. Minden erőfeszítés hiábavaló!
Memóriába helyeztük a komponenst, de a 'click' gomb megnyomásakor
a Items komponens továbbra is
minden alkalommal újrarajzolódik.
Az a helyzet, hogy amikor a szülő
komponens újrarajzolódik, a függvényei
újra létrejönnek - ez vonatkozik a mi
addItem függvényünkre is, amelyet átadunk a
Items-nek.
Pontosan ebben a pillanatban segít a
useCallback hook. Alkalmazzuk
most. Először importáljuk be az
App-be:
import { useCallback } from 'react';
Ezután alakítsuk át az egyszerű függvénydeklarációt
addItem-ből
Function Expression-né, adjuk meg mint
első paramétert a useCallback-nak
a függvényünket visszahívó formájában. Második
paraméterként szögletes zárójelekben adjuk meg
a függőségeket - minden reaktív változót,
amely részt vesz a függvényben, esetünkben
ez a items tömb:
const addItem = useCallback(() => {
setItems(() => [...items, 'New item']);
}, [items]);
Kész! Így gyorsítótáraztuk a
függvényt. Nyomjuk meg újra a gombokat és
láthatjuk, hogy most a 'click' gomb
megnyomásakor a gyermek komponens nem
rajzolódik újra.
Hozz létre egy App komponenst, helyezz
bele egy szöveggel ellátott bekezdést. Hozz létre
egy állapotot 'text' kezdőértékkel
és írd ki egy bekezdésben. Legyen úgy, hogy a bekezdésre kattintáskor
a szöveg végéhez
hozzáadódik egy felkiáltójel.
Hozz létre egy gyermek komponenst, Products-et,
amelyben lesz egy gomb egy új termék hozzáadásához.
Helyezd el az App-ben.
A szülő komponensben hozz létre egy állapotot
a termékek tömbjével és egy függvényt egy új termék hozzáadásához.
Add át ezeket
prop-ként a gyermek komponensnek, jelenítsd meg benne
az átadott tömböt egy ul listaként.
A Products-ben írd ki a konzolra a
'products render' szöveget.
Csomagold be a Products-et memo-ba.
Kattintsgass a bekezdésre és a gombra. Győződj meg róla,
hogy a bekezdésre kattintáskor a gyermek komponens
mégis újrarajzolódik.
Gyorsítótárazd a termékek hozzáadására szolgáló függvényt,
tegyed bele a useCallback hook-ba.
Kattintsgass a bekezdésre és a gombra. Győződj meg róla,
hogy a bekezdésre kattintáskor a gyermek komponens
már nem rajzolódik újra.