Gebruik van die gebruikCallback-hook vir prestasie-optimalisering in React
In hierdie les sal ons die volgende huk vir prestasie-optimalisering oorweeg: useCallback.
Die huk useCallback is soortgelyk aan die useMemo API, die verskil is dat die eerste 'n waarde tussen herrenderings kas, en die tweede - 'n callback. Dit stel ons in staat om nie duur funksies onnodig te herlaai nie en kan gebruik word wanneer 'n funksie oorgedra word na kinderkomponente.
Kom ons kyk na 'n voorbeeld. Laat ons eers 'n App komponent skep en 'n num staat daarin instel:
const [num, setNum] = useState(0);
Kom ons neem aan ons het 'n knoppie wat, wanneer daarop geklik word, num met 1 verhoog, en 'n paragraaf waarin ons die waarde van num sal vertoon:
return (
<div>
<button onClick={() => setNum(num + 1)}>click</button>
<p>clicks: {num}</p>
</div>
);
Veronderstel nou dat ons in App ook 'n lys met items vertoon, wat ons sal uitbrei deur op 'n ander knoppie te druk. Om die items van hierdie lys te stoor, sal ons 'n items staat skep:
const [items, setItems] = useState([]);
En dan skryf ons 'n addItem funksie om dit by te voeg:
function addItem() {
setItems([...items, 'new item']);
}
Kom ons skryf nou die kode om die lysitems te vertoon en plaas dit in 'n kinderkomponent genaamd Items, wat die lys items en die funksie om dit by te voeg as props sal ontvang. Onthou om 'n console.log by te voeg om te sien wanneer ons Items herrender:
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;
Plaas Items aan die einde van die App komponent en gee die items array en die addItem funksie daaraan:
return (
<>
<div>
<button onClick={() => setNum(num + 1)}>click</button>
<p>clicks: {num}</p>
<br />
</div>
<Items items={items} addItem={addItem} />
</>
);
Kom ons klik nou op die knoppies en maak seker dat num styg en nuwe items by die lys gevoeg word. As ons die konsole oopmaak, sal ons sien dat ons lys elke keer herrender, selfs as ons op die knoppie klik wat num verhoog.
As ons 'n klein lysie het, is alles in orde, maar wat as daar verwag word dat dit baie groot sal wees en daar baie ander dinge is? Geen probleem nie - sal jy sê, want in die vorige les het ons die memo API bespreek om presies onnodige komponentherrenderings te vermy.
Kom ons pak dan ons Items komponent in memo en alles is reg. Terloops, dit kan direk gedoen word wanneer Items geëksporteer word:
export default memo(Items);
Moenie vergeet om memo te importeer nie:
import { memo } from 'react';
Maak nou die konsole oop en klik op die knoppies. Alle pogings tevergeefs! Ons het die komponent gememoïseer, maar wanneer die 'click' knoppie gedruk word, herrender die Items komponent nog steeds elke keer.
Die rede is dat wanneer die ouerkomponent herrender, sy funksies van nuut geskep word - dit sluit ons addItem funksie in, wat ons na Items oordra.
Presies op hierdie stadium sal die useCallback huk ons help. Kom ons pas dit toe. Eers, importeer dit in App:
import { useCallback } from 'react';
Verander dan die eenvoudige deklarasie van die addItem funksie na 'n Function Expression, spesifiseer ons funksie as 'n callback as die eerste parameter vir useCallback. As tweede parameter, in vierkantige hakies, spesifiseer ons die afhanklikhede - alle reaktiewe veranderlikes wat in die funksie deelneem, in ons geval is dit die items array:
const addItem = useCallback(() => {
setItems(() => [...items, 'New item']);
}, [items]);
Klaar! Sodoende het ons die funksie gekas. Klik weer op die knoppies en sien dat wanneer die 'click' knoppie gedruk word, ons kinderkomponent nie meer herrender nie.
Skep 'n App komponent, plaas 'n paragraaf met teks daarin. Skep 'n staat met aanvanklike waarde 'text' en vertoon dit in die paragraaf. Laat, wanneer op die paragraaf geklik word, 'n uitroepteken aan die einde van die teks gevoeg word.
Skep 'n kinderkomponent Products, waarin jy 'n knoppie het om 'n nuwe produk by te voeg. Plaas dit in App. Skep in die ouerkomponent 'n staat met 'n array van produkte en 'n funksie om 'n nuwe produk by te voeg. Gee dit as props aan die kinderkomponent, vertoon die oorgedraagde array daarin as 'n ul lys.
In Products, vertoon die teks 'products render' in die konsole. Pak Products in memo. Klik op die paragraaf en knoppie. Maak seker dat wanneer op die paragraaf geklik word, die kinderkomponent steeds herrender.
Kas die funksie om produkte by te voeg deur dit in die useCallback huk te pak. Klik op die paragraaf en knoppie. Maak seker dat wanneer op die paragraaf geklik word, die kinderkomponent nie meer herrender nie.