Prestandaoptimeringshooken useCallback i React
I den här lektionen kommer vi att titta på följande
hook för prestandaoptimering
useCallback.
Hooken useCallback liknar API:et useMemo,
skillnaden är att den första
cachar ett värde mellan renderingar
av skärmen, medan den andra cachar en återanrop.
Detta gör att vi kan undvika att köra resurskrävande
funktioner när det inte behövs och kan
användas när man
skickar en funktion
till underordnade komponenter.
Låt oss förstå det bättre med ett exempel.
Låt oss först skapa en komponent App
och skapa ett tillstånd num i den:
const [num, setNum] = useState(0);
Låt oss ha en knapp, vid klick
på vilken num ökar
med 1, och ett stycke där vi
kommer att visa värdet på num:
return (
<div>
<button onClick={() => setNum(num + 1)}>klicka</button>
<p>klick: {num}</p>
</div>
);
Och nu, låt oss anta att vi i
App också visar någon lista
med element som vi kommer att lägga till
genom att klicka på en annan knapp. För att lagra
elementen i denna lista skapar vi
tillståndet items:
const [items, setItems] = useState([]);
Och sedan skriver vi funktionen addItem
för att lägga till dem:
function addItem() {
setItems([...items, 'new item']);
}
Låt oss nu skriva koden för att visa
listelementen och flytta ut den till en underordnad
komponent Items, som som
props kommer att ta emot en array med element
och en funktion för att lägga till dem. Låt oss inte glömma
att lägga till en utskrift till konsolen för att se
när vår Items kommer att
återrendera:
function Items({ items, addItem }) {
const result = items.map((item, index) => {
return <p key={index}>{item}</p>;
});
console.log('Items render');
return (
<div>
<h3>Våra föremål</h3>
{result}
<button onClick={addItem}>lägg till föremål</button>
</div>
);
}
export default Items;
Låt oss placera Items i slutet av komponenten
App och skicka arrayen
items och funktionen för att lägga till
element addItem till den:
return (
<>
<div>
<button onClick={() => setNum(num + 1)}>klicka</button>
<p>klick: {num}</p>
<br />
</div>
<Items items={items} addItem={addItem} />
</>
);
Och låt oss nu klicka på knapparna
och se till att num ökar och
att nya element läggs till i listan.
Och om vi öppnar konsolen kommer vi att se att
vår lista återrenderas varje
gång, även om vi klickar på knappen
som ökar num.
Om vi har en liten lista är allt
okej, men tänk om den är
stor och det finns mycket annat där?
Inget problem - säger du, för i förra
lektionen tittade vi på API:et memo,
för att just undvika onödiga återrenderingar
av en komponent.
Så låt oss slå in vår komponent
Items i memo och det är klart.
Förresten, detta kan göras direkt
vid export av Items:
export default memo(Items);
Låt oss inte glömma att importera memo:
import { memo } from 'react';
Och låt oss nu öppna konsolen och klicka
på knapparna. Alla ansträngningar förgäves! Vi
memoiserade komponenten, men när vi klickade
på knappen 'klicka' återrendras komponenten
Items fortfarande varje gång.
Anledningen är att när den överordnade
komponenten återrendras, skapas dess funktioner
på nytt - detta gäller även vår
funktion addItem, som vi skickar till
Items.
Det är just i detta ögonblick som hooken
useCallback kommer att hjälpa oss. Låt oss använda
den. Först importerar vi den till
App:
import { useCallback } from 'react';
Sedan omvandlar vi den enkla deklarationen av funktionen
addItem till ett
Funktionsuttryck, anger som
första parameter för useCallback
vår funktion som en återanropsfunktion. Som
andra parameter i hakparenteser anger vi
beroenden - alla reaktiva variabler
som ingår i funktionen, i vårt fall
är det arrayen items:
const addItem = useCallback(() => {
setItems(() => [...items, 'Nytt föremål']);
}, [items]);
Klart! På så sätt har vi cachat
funktionen. Vi klickar igen på knapparna och
ser att nu, när vi klickar på knappen
'klicka', återrendras vår underordnade komponent inte.
Skapa en komponent App, placera
ett stycke med text i den. Skapa
ett tillstånd med startvärdet 'text'
och visa det i stycket. Låt det så att vid klick
på stycket läggs ett utropstecken
till i slutet av texten.
Skapa en underordnad komponent Products,
där du har en knapp för att lägga till
en ny produkt. Placera den i App.
Skapa ett tillstånd i den överordnade komponenten
med en array av produkter och en funktion för att lägga till
en ny produkt. Skicka dem som
props till den underordnade, visa arrayen i den
som en lista ul.
I Products, skriv ut texten
'products render' i konsolen.
Sätt in Products i memo.
Klicka på stycket och knappen. Se till
att när du klickar på stycket återrendras den underordnade komponenten
ändå.
Cacha funktionen för att lägga till
produkter genom att slå in den i hooken useCallback.
Klicka på stycket och knappen. Se till
att när du klickar på stycket återrendras den underordnade komponenten
inte längre.