Hook-ul de optimizare a performanței useMemo în React
Primul hook pentru optimizarea
performanței pe care îl vom analiza
- este useMemo.
Acest hook ajută la cache-uirea rezultatelor operațiilor intensive în resurse între momentele de re-randare a ecranului și, în consecință, poate ajuta la evitarea unor calcule voluminoase inutile. Acest tip de cache-uire se mai numește memoizare.
Să vedem cum funcționează. Să
creăm un component cu un buton și
un titlu h3:
return (
<div>
<h3>Text</h3>
<button>click</button>
</div>
);
Și acum să facem astfel încât la click
pe titlu, culoarea acestuia să se schimbe din portocaliu
în verde și invers. Pentru început
să creăm un stadiu isGreen:
const [isGreen, setIsGreen] = useState(false);
Să adăugăm în atributul style al titlului
o condiție de schimbare a culorii titlului și
să atașăm un handler de click:
<h3 onClick={() => setIsGreen(!isGreen)}
style={{ color: isGreen ? 'green' : 'orangered' }}
>Text</h3>
Să presupunem că avem și o valoare, care va crește la click pe butonul nostru cu o unitate. Să creăm pentru aceasta un stadiu:
const [num, setNum] = useState(0);
Să adăugăm manipularea click-ului pe buton:
<button onClick={() => setNum(num + 1)}>
clicks
</button>
Să presupunem că avem și o funcție
square, care va returna
pătratul valorii num. Rezultatul
apelului funcției îl vom scrie într-o
variabilă result:
const result = square(num);
function square(num) {
return num * num;
}
Să afișăm result în textul butonului:
<button onClick={() => setNum(num + 1)}>
clicks: {result}
</button>
Ca rezultat, am obținut următoarele:
la click pe buton se schimbă valoarea
num, care apoi este ridicată
la pătrat, iar la click pe titlu
se schimbă culoarea titlului.
Avem un component foarte mic, totul funcționează rapid, în ciuda faptului că la click pe titlu pentru a-i schimba culoarea, întregul component se redesenează din nou, în consecință au loc din nou și calculele, care sunt legate de buton, asta chiar și atunci când nu l-am atins. Și acum imaginați-vă dacă calculele noastre ar fi fost voluminoase și totul ar fi fost recalculat din nou de fiecare dată.
Hai să facem funcția noastră un pic mai grea, acum va "gândi" puțin mai mult. Astfel vom simula calculele lungi:
function square(num) {
let startTime = performance.now();
while (performance.now() - startTime < 500) {
// Doar nu face nimic ...
}
return num * num;
}
Apăsați acum pe titlu. Se pare
că acum, din cauza funcției cu durată lungă de execuție
square (dar butonul nu îl atingem)
trebuie să așteptăm o veșnicie pentru ca
titlul să-și schimbe culoarea!
Aici vine în ajutorul nostru hook-ul
useMemo. Pentru aceasta, trebuie ca primul
parametru să îi transmitem o funcție care calculează
valoarea pe care dorim să o cache-uim,
această funcție trebuie să fie pură și să nu
accepte niciun parametru. Iar al doilea
parametru - dependențele în paranteze pătrate,
cu alte cuvinte, toate valorile reactive
care participă în codul
funcției. Astfel, în result
vom scrie acum o astfel de construcție:
const result = useMemo(() => square(num), [num]);
Să apăsăm din nou pe titlu. Acum,
dacă nu atingem butonul cu calculele
și nu schimbăm astfel valoarea stadiului
num, atunci nimic nu se recalculează,
și React afișează valoarea cache-uită
în buton, de aceea titlul nostru
își schimbă rapid culoarea.
Creați un component App, plasați
în el un paragraf. Creați un stadiu text
cu valoarea inițială 'react',
lăsați valoarea stadiului să se afișeze
ca text al paragrafului. La click
pe paragraf, adăugați la sfârșitul textului
un semn de exclamare.
Creați încă un stadiu num, cu
valoarea inițială 0. Plasați în
App încă un paragraf. Faceți astfel încât,
la click pe el, num
să crească cu 1.
Și acum adăugați în App funcția
triple, care ca
parametru primește num și
întoarce valoarea sa triplată.
Puneți rezultatul apelării funcției
în variabila result. Afișați
result ca text al celui de-al doilea
paragraf. Apăsați pe rând pe paragrafe,
observați cât de încet se adaugă
semnele de exclamare.
Remediați situația, împachetând funcția lentă
triple în useMemo.