Memorizarea este o tehnică de optimizare, asemănătoare stocării în cache. Funcționează prin stocarea rezultatelor anterioare ale unui apel de funcție și prin utilizarea acestor rezultate data viitoare când funcția rulează. Este util în special în aplicațiile grele de calcul care repetă apelurile de funcție pe aceiași parametri.
Puteți utiliza memorarea în JavaScript simplu și, de asemenea, în React, în câteva moduri diferite.
Memorare în JavaScript
Pentru a memoriza o funcție în JavaScript, trebuie să stocați rezultatele acelei funcție într-un cache. Cache-ul poate fi un obiect cu argumentele ca chei și rezultatele ca valori.
Când apelați această funcție, ea verifică mai întâi dacă rezultatul este prezent în cache înainte de a rula. Dacă este, returnează rezultatele stocate în cache. În caz contrar, se execută.
Luați în considerare această funcție:
funcţiepătrat(num) {
întoarcere num * num
}
Funcția preia un argument și returnează pătratul acestuia.
Pentru a rula funcția, apelați-o cu un număr ca acesta:
pătrat(5) // 25
Cu 5 drept argument, square() va rula destul de repede. Cu toate acestea, dacă ar fi să calculați pătratul de 70.000, ar exista o întârziere vizibilă. Nu cu mult, dar totuși o întârziere. Acum, dacă ați apela funcția de mai multe ori și ați trece de 70.000, ați experimenta o întârziere la fiecare apel.
Puteți elimina această întârziere folosind memorarea.
const memoizedSquare = () => {
lăsa cache = {};
întoarcere (num) => {
dacă (num in cache) {
console.log('Reutilizarea valorii din cache');
întoarcere cache[num];
} altfel {
console.log('Rezultatul calculului');
lăsa rezultat = num * num;
// cache cel nourezultatvaloarepentruUrmătorultimp
cache[num] = rezultat;
întoarcere rezultat;
}
}
}
În acest exemplu, funcția verifică dacă rezultatul a fost calculat înainte, verificând dacă acesta există în obiectul cache. Dacă are, returnează valoarea deja calculată.
Când funcția primește un număr nou, calculează o nouă valoare și stochează rezultatele în cache înainte de a reveni.
Din nou, acest exemplu este destul de simplu, dar explică cum ar funcționa memorarea pentru a îmbunătăți performanța unui program.
Ar trebui să memorați doar funcții pure. Aceste funcții returnează același rezultat atunci când treceți aceleași argumente. Dacă utilizați memorarea pentru funcții impure, nu vă veți îmbunătăți performanța, ci vă veți crește costul general. Asta pentru că alegeți viteza în detrimentul memoriei de fiecare dată când memorați o funcție.
Memorare în React
Dacă doriți să optimizați componentele React, React oferă memorare prin cârligul useMemo(), React.memo și useCallBack().
Folosind useMemo()
useMemo() este un Cârlig de reacție care acceptă o funcție și o matrice de dependențe.
const memoizedValue = useMemo(() => computeExpensiveValue (a, b), [a, b]);
Memorează valoarea returnată de acea funcție. Valorile din tabloul de dependențe dictează momentul în care funcția este executată. Numai când se schimbă funcția este executată din nou.
De exemplu, următoarea componentă a aplicației are o valoare memorată numită rezultat.
import { foloseșteMemo } din "reacţiona"
funcţieApp(valoare) {
const pătrat = (valoare) => {
întoarcere valoare * valoare
}
const rezultat = useMemo(
() => pătrat (valoare),
[valoare]
);
întoarcere (
<div>{rezultat (5)}</div>
)
}
Componenta aplicației apelează square() la fiecare randare. Performanța se va degrada dacă componenta aplicației este redată de mai multe ori din cauza Reacții de recuzită modificarea sau actualizarea stării, mai ales dacă funcția square() este costisitoare.
Cu toate acestea, deoarece useMemo() memorează în cache valorile returnate, funcția pătrat nu este executată în fiecare re-rendare decât dacă argumentele din matricea de dependențe se modifică.
Folosind React.memo()
React.memo() este o componentă de ordin superior care acceptă o componentă React și o funcție ca argumente. Funcția determină când trebuie actualizată componenta.
Funcția este opțională și, dacă nu este furnizată, React.memo face o comparație de copiere superficială a elementelor de recuzită actuale ale componentei cu elementele de recuzită anterioare. Dacă elementele de recuzită sunt diferite, declanșează o actualizare. Dacă elementele de recuzită sunt aceleași, omite re-rendarea și reutiliza valorile memorate.
Funcția opțională acceptă recuzita anterioară și recuzita următoare ca argumente. Apoi puteți compara în mod explicit aceste elemente de recuzită pentru a decide dacă actualizați sau nu componenta.
Reacţiona.notificare(Componentă, [areEqual (prevProps, nextProps)])
Să ne uităm mai întâi la un exemplu fără argumentul funcției opționale. Mai jos este o componentă numită Comentarii care acceptă numele și recuzita de e-mail.
funcţieComentarii ({nume, comentariu, aprecieri}) {
întoarcere (
<div>
<p>{Nume}</p>
<p>{cometariu}</p>
<p>{îi place}</p>
</div>
)
}
Componenta de comentarii memorate va avea React.memo înfășurat astfel:
const MemoizedComment = React.memo (Comentariu)
Puteți apela, apoi îl puteți apela ca orice altă componentă React.
<MemoizedComment name="Maria" comentariu="Memorarea este grozavă" aprecieri=1/>
Dacă doriți să efectuați singur comparația elementelor de recuzită, transmiteți următoarea funcție la React.memo ca al doilea argument.
import Reacţiona din "reacţiona"
funcţiecheckCommentProps(prevProps, nextProps) {
întoarcere prevProps.name nextProps.name
&& prevProps.comment nextProps.comment
&& prevProps.likes nextProps.likes
}
const MemoizedComment = React.memo (Comentarii, checkCommentProps)
Dacă checkProfileProps returnează true, componenta nu este actualizată. În caz contrar, este redat din nou.
Funcția personalizată este utilă atunci când doriți să personalizați redarea. De exemplu, îl puteți folosi pentru a actualiza componenta Comentarii numai atunci când se modifică numărul de aprecieri.
Spre deosebire de cârligul useMemo() care memorează numai valoarea returnată a unei funcții, React.memo memorează întreaga funcție.
Utilizați React.memo numai pentru componente pure. De asemenea, pentru a reduce costurile de comparație, memorați doar componente ale căror elemente de recuzită se schimbă des.
Folosind useCallBack()
Puteți folosi cârligul useCallBack() pentru a memoriza componentele functionale.
const memoizedCallback = useCallback(
() => {
face ceva (a, b);
},
[a, b],
);
Funcția este actualizată numai atunci când se modifică valorile din matricea de dependențe. Cârligul funcționează ca apelul useMemo(), dar memorează componenta funcției între randări în loc să memoreze valori.
Luați în considerare următorul exemplu de funcție memorată care apelează un API.
import { useCallback, useEffect } din "reacţiona";
const Component = () => {
const getData = useCallback(() => {
console.log('apelați un API');
}, []);
useEffect(() => {
Obțineți date();
}, [Obțineți date]);
};
Funcția getData() numită în useEffect va fi apelată din nou numai atunci când valoarea getData se schimbă.
Ar trebui să memorezi?
În acest tutorial, ați învățat ce este memorarea, beneficiile sale și cum să o implementați în JavaScript și React. Cu toate acestea, trebuie să știți că React este deja rapid. În cele mai multe cazuri, memorarea componentelor sau a valorilor adaugă costuri de comparație și nu îmbunătățește performanța. Din acest motiv, memorați doar componente scumpe.
React 18 a introdus și noi cârlige precum useId, useTransition și useInsertionEffect. Le puteți folosi pentru a îmbunătăți performanța și experiența utilizatorului aplicațiilor React.