Memoisering er en optimeringsteknik, der ligner caching. Det fungerer ved at gemme de tidligere resultater af et funktionskald og bruge disse resultater, næste gang funktionen kører. Det er især nyttigt i beregningstunge apps, der gentager funktionskald på de samme parametre.
Du kan bruge memoisering i almindelig JavaScript og også i React på et par forskellige måder.
Memoisering i JavaScript
For at huske en funktion i JavaScript, skal du gemme resultaterne af denne funktion i en cache. Cachen kan være et objekt med argumenterne som nøgler og resultater som værdier.
Når du kalder denne funktion, tjekker den først, om resultatet er til stede i cachen, før den kører. Hvis det er, returnerer det de cachelagrede resultater. Ellers udføres det.
Overvej denne funktion:
fungerefirkant(num) {
Vend tilbage num * num
}
Funktionen tager et argument ind og returnerer dets kvadrat.
For at køre funktionen skal du kalde den med et nummer som dette:
firkant(5) // 25
Med 5 som argument vil square() løbe ret hurtigt. Men hvis du skulle beregne kvadratet på 70.000, ville der være en mærkbar forsinkelse. Ikke meget, men alligevel en forsinkelse. Nu, hvis du skulle ringe til funktionen flere gange og passere 70.000, ville du opleve en forsinkelse i hvert opkald.
Du kan eliminere denne forsinkelse ved at bruge huskeseddel.
konst memoizedSquare = () => {
lade cache = {};
Vend tilbage (antal) => {
hvis (antal in cache) {
console.log('Genbruger cachelagret værdi');
Vend tilbage cache[num];
} andet {
console.log('Beregner resultat');
lade resultat = antal * antal;
// cache det nyresultatværditilNæstetid
cache[num] = resultat;
Vend tilbage resultat;
}
}
}
I dette eksempel kontrollerer funktionen, om den har beregnet resultatet før, ved at kontrollere, om den findes i cache-objektet. Hvis den har, returnerer den den allerede beregnede værdi.
Når funktionen modtager et nyt tal, beregner den en ny værdi og gemmer resultaterne i cachen, før den vender tilbage.
Igen er dette eksempel ret simpelt, men det forklarer, hvordan memoization ville fungere for at forbedre ydeevnen af et program.
Du bør kun huske rene funktioner. Disse funktioner returnerer det samme resultat, når du sender de samme argumenter ind. Hvis du bruger memoization på urene funktioner, vil du ikke forbedre ydeevnen, men øge din overhead. Det er fordi du vælger hastighed frem for hukommelse, hver gang du husker en funktion.
Memoisering i React
Hvis du ønsker at optimere React-komponenter, giver React huskeseddel via useMemo()-krogen, React.memo og useCallBack().
Brug af useMemo()
useMemo() er en Reaktionskrog der accepterer en funktion og et afhængighedsarray.
konst memoizedValue = useMemo(() => computeExpensiveValue (a, b), [a, b]);
Den husker den værdi, der returneres fra den funktion. Værdierne i afhængighedsarrayet dikterer, hvornår funktionen udføres. Først når de ændres, udføres funktionen igen.
For eksempel har den følgende app-komponent en husket værdi kaldet resultat.
importere { useMemo } fra "reagere"
fungereApp(værdi) {
konst kvadrat = (værdi) => {
Vend tilbage værdi * værdi
}
konst resultat = brug Memo(
() => kvadrat (værdi),
[ værdi ]
);
Vend tilbage (
<div>{resultat (5)}</div>
)
}
App-komponenten kalder square() på hver gengivelse. Ydeevnen forringes, hvis App-komponenten gengives mange gange pga Reager rekvisitter ændring eller tilstandsopdatering, især hvis square()-funktionen er dyr.
Men da useMemo() cacher de returnerede værdier, udføres kvadratfunktionen ikke i hver gengivelse, medmindre argumenterne i afhængighedsarrayet ændres.
Brug af React.memo()
React.memo() er en højere ordens komponent, der accepterer en React komponent og en funktion som argumenter. Funktionen bestemmer, hvornår komponenten skal opdateres.
Funktionen er valgfri, og hvis den ikke leveres, laver React.memo en overfladisk sammenligning af komponentens nuværende rekvisitter med dens tidligere rekvisitter. Hvis rekvisitterne er anderledes, udløser det en opdatering. Hvis rekvisitterne er de samme, springer den gengivelsen over og genbruger de huskede værdier.
Den valgfri funktion accepterer de foregående rekvisitter og de næste rekvisitter som argumenter. Du kan derefter udtrykkeligt sammenligne disse rekvisitter for at beslutte, om du vil opdatere komponenten eller ej.
Reagere.memo(Komponent, [areEqual (prevProps, nextProps)])
Lad os først se på et eksempel uden det valgfri funktionsargument. Nedenfor er en komponent kaldet Kommentarer, der accepterer navn og e-mail-rekvisitter.
fungereKommentarer ({navn, kommentar, synes godt om}) {
Vend tilbage (
<div>
<s>{navn}</s>
<s>{kommentar}</s>
<s>{kan lide}</s>
</div>
)
}
Den huskede kommentarkomponent vil have React.memo viklet rundt på denne måde:
konst MemoizedComment = React.memo (Kommentar)
Du kan kalde det og derefter kalde det som enhver anden React-komponent.
<MemoizedComment name="Mary" kommentar="Memoization er fantastisk" synes godt om=1/>
Hvis du selv vil udføre rekvisitsammenligningen, skal du videregive følgende funktion til React.memo som det andet argument.
importere Reagere fra "reagere"
fungerecheckCommentProps(prevProps, nextProps) {
Vend tilbage prevProps.name næsteProps.name
&& prevProps.comment nextProps.comment
&& prevProps.likes nextProps.likes
}
konst MemoizedComment = React.memo (Kommentarer, checkCommentProps)
Hvis checkProfileProps returnerer true, opdateres komponenten ikke. Ellers gengives det igen.
Den brugerdefinerede funktion er nyttig, når du ønsker at tilpasse gengivelsen. For eksempel kan du kun bruge den til at opdatere Kommentar-komponenten, når antallet af likes ændres.
I modsætning til useMemo() hook, der kun husker den returnerede værdi af en funktion, husker React.memo hele funktionen.
Brug kun React.memo til rene komponenter. For at reducere sammenligningsomkostningerne skal du også huske komponenter, hvis rekvisitter ofte ændres.
Brug af useCallBack()
Du kan bruge useCallBack()-krogen til at huske funktionskomponenter.
konst memoizedCallback = useCallback(
() => {
gøre Noget (a, b);
},
[a, b],
);
Funktionen opdateres kun, når værdierne i afhængighedsarrayet ændres. Krogen fungerer som useMemo()-tilbagekaldet, men den husker funktionskomponenten mellem gengivelser i stedet for at huske værdier.
Overvej følgende eksempel på en memoiseret funktion, der kalder en API.
importere { useCallback, useEffect } fra "reagere";
konst Komponent = () => {
konst getData = useCallback(() => {
console.log('kalde en API');
}, []);
useEffect(() => {
getData();
}, [getData]);
};
GetData()-funktionen kaldet i useEffect vil kun blive kaldt igen, når getData-værdien ændres.
Skal du huske?
I denne tutorial lærte du, hvad memoization er, dets fordele, og hvordan du implementerer det i JavaScript og React. Du skal dog vide, at React allerede er hurtig. I de fleste tilfælde tilføjer huskekomponenter eller værdier sammenligningsomkostninger og forbedrer ikke ydeevnen. På grund af dette skal du kun huske dyre komponenter.
React 18 introducerede også nye hooks som useId, useTransition og useInsertionEffect. Du kan bruge disse til at forbedre ydeevnen og brugeroplevelsen af React-applikationer.