Celovit vodnik za optimizacijo zmogljivosti aplikacij React z uporabo useMemo, useCallback in React.memo. Naučite se preprečevati nepotrebne ponovne upodobitve.
Optimizacija zmogljivosti React: obvladovanje useMemo, useCallback in React.memo
React, priljubljena knjižnica JavaScript za gradnjo uporabniških vmesnikov, je znana po svoji arhitekturi, ki temelji na komponentah, in deklarativnem slogu. Vendar lahko z naraščajočo kompleksnostjo aplikacij zmogljivost postane skrb. Nepotrebne ponovne upodobitve komponent lahko povzročijo počasno delovanje in slabo uporabniško izkušnjo. Na srečo React ponuja več orodij za optimizacijo zmogljivosti, vključno z useMemo
, useCallback
in React.memo
. Ta vodnik se poglobi v te tehnike, ki ponujajo praktične primere in uporabne vpoglede, ki vam pomagajo graditi visokozmogljive aplikacije React.
Razumevanje ponovnih upodobitev React
Preden se potopimo v tehnike optimizacije, je ključnega pomena razumeti, zakaj se ponovne upodobitve zgodijo v Reactu. Ko se stanje ali propz komponente spremenijo, React sproži ponovno upodobitev te komponente in potencialno njenih podrejenih komponent. React uporablja virtualni DOM za učinkovito posodabljanje dejanskega DOM-a, vendar lahko pretirane ponovne upodobitve še vedno vplivajo na zmogljivost, zlasti v kompleksnih aplikacijah. Predstavljajte si globalno platformo za e-trgovino, kjer se cene izdelkov pogosto posodabljajo. Brez optimizacije bi majhna sprememba cene lahko sprožila ponovne upodobitve po celotnem seznamu izdelkov, kar bi vplivalo na brskanje uporabnikov.
Zakaj se komponente ponovno upodabljajo
- Spremembe stanja: Ko se stanje komponente posodobi z uporabo
useState
aliuseReducer
, React ponovno upodobi komponento. - Spremembe propzov: Če komponenta prejme nove propze od svoje nadrejene komponente, se bo ponovno upodobila.
- Ponovne upodobitve nadrejenih: Ko se nadrejena komponenta ponovno upodobi, se bodo njene podrejene komponente privzeto prav tako ponovno upodobile, ne glede na to, ali so se njihovi propzi spremenili.
- Spremembe konteksta: Komponente, ki uporabljajo React Context, se bodo ponovno upodobile, ko se vrednost konteksta spremeni.
Cilj optimizacije zmogljivosti je preprečiti nepotrebne ponovne upodobitve, kar zagotavlja, da se komponente posodobijo le, ko so se njihovi podatki dejansko spremenili. Razmislite o scenariju, ki vključuje vizualizacijo podatkov v realnem času za analizo delniškega trga. Če se komponente grafov nepotrebno ponovno upodabljajo ob vsaki manjši posodobitvi podatkov, bo aplikacija postala neodzivna. Optimizacija ponovnih upodobitev bo zagotovila gladko in odzivno uporabniško izkušnjo.
Predstavljamo useMemo: memoiziranje dragih izračunov
useMemo
je kaveljček React, ki memoizira rezultat izračuna. Memoizacija je optimizacijska tehnika, ki shranjuje rezultate dragih klicev funkcij in ponovno uporablja te rezultate, ko se pojavijo enaki vhodi. To preprečuje potrebo po nepotrebnem ponovnem izvajanju funkcije.
Kdaj uporabiti useMemo
- Dragi izračuni: Ko mora komponenta izvesti izračun, ki je računsko intenziven, na podlagi svojih propzov ali stanja.
- Referenčna enakost: Pri podajanju vrednosti kot propza podrejeni komponenti, ki se zanaša na referenčno enakost, da se ugotovi, ali se bo ponovno upodobila.
Kako deluje useMemo
useMemo
sprejme dva argumenta:
- Funkcija, ki izvaja izračun.
- Seznam odvisnosti.
Funkcija se izvede le, ko se spremeni ena od odvisnosti v seznamu. Sicer useMemo
vrne predhodno memoizirano vrednost.
Primer: izračun Fibonaccijevega zaporedja
Fibonaccijevo zaporedje je klasičen primer računsko intenzivnega izračuna. Ustvarimo komponento, ki izračuna n-to Fibonaccievo število z uporabo useMemo
.
import React, { useState, useMemo } from 'react';
function Fibonacci({ n }) {
const fibonacciNumber = useMemo(() => {
console.log('Calculating Fibonacci...'); // Demonstrates when the calculation runs
function calculateFibonacci(num) {
if (num <= 1) {
return num;
}
return calculateFibonacci(num - 1) + calculateFibonacci(num - 2);
}
return calculateFibonacci(n);
}, [n]);
return Fibonacci({n}) = {fibonacciNumber}
;
}
function App() {
const [number, setNumber] = useState(5);
return (
setNumber(parseInt(e.target.value))}
/>
);
}
export default App;
V tem primeru se funkcija calculateFibonacci
izvede le, ko se propz n
spremeni. Brez useMemo
bi se funkcija izvajala ob vsaki ponovni upodobitvi komponente Fibonacci
, tudi če bi n
ostal enak. Predstavljajte si, da se ta izračun zgodi na globalni finančni nadzorni plošči – vsak premik na trgu povzroči popoln ponovni izračun, kar vodi do znatne zakasnitve. useMemo
to preprečuje.
Predstavljamo useCallback: memoiziranje funkcij
useCallback
je še en kaveljček React, ki memoizira funkcije. Preprečuje ustvarjanje nove instance funkcije ob vsaki upodobitvi, kar je lahko še posebej koristno pri podajanju povratnih klicev kot propzov podrejenim komponentam.
Kdaj uporabiti useCallback
- Podajanje povratnih klicev kot propzov: Pri podajanju funkcije kot propza podrejeni komponenti, ki uporablja
React.memo
alishouldComponentUpdate
za optimizacijo ponovnih upodobitev. - Obravnavalci dogodkov: Pri definiranju funkcij obravnavalcev dogodkov znotraj komponente za preprečevanje nepotrebnih ponovnih upodobitev podrejenih komponent.
Kako deluje useCallback
useCallback
sprejme dva argumenta:
- Funkcija, ki jo je treba memoizirati.
- Seznam odvisnosti.
Funkcija se ponovno ustvari le, ko se spremeni ena od odvisnosti v seznamu. Sicer useCallback
vrne isto instanco funkcije.
Primer: obravnavanje klika na gumb
Ustvarimo komponento z gumbom, ki sproži povratni klic. Uporabili bomo useCallback
za memoiziranje povratnega klica.
import React, { useState, useCallback } from 'react';
function Button({ onClick, children }) {
console.log('Button re-rendered'); // Demonstrates when the Button re-renders
return ;
}
const MemoizedButton = React.memo(Button);
function App() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Button clicked');
setCount((prevCount) => prevCount + 1);
}, []); // Empty dependency array means the function is only created once
return (
Count: {count}
Increment
);
}
export default App;
V tem primeru je funkcija handleClick
ustvarjena le enkrat, ker je seznam odvisnosti prazen. Ko se komponenta App
ponovno upodobi zaradi spremembe stanja count
, funkcija handleClick
ostane enaka. Komponenta MemoizedButton
, zavita s React.memo
, se bo ponovno upodobila le, če se njeni propzi spremenijo. Ker propz onClick
(handleClick
) ostane enak, se komponenta Button
ne ponovi nepotrebno. Predstavljajte si interaktivno zemljevidno aplikacijo. Vsakič, ko uporabnik nekaj naredi, se lahko dotakne na ducate komponent gumbov. Brez useCallback
bi se ti gumbi nepotrebno ponovno upodobili, kar bi ustvarilo počasno izkušnjo. Uporaba useCallback
zagotavlja bolj gladko interakcijo.
Predstavljamo React.memo: memoiziranje komponent
React.memo
je komponenta višjega reda (HOC), ki memoizira funkcijsko komponento. Preprečuje ponovno upodobitev komponente, če se njeni propzi niso spremenili. To je podobno PureComponent
za razredne komponente.
Kdaj uporabiti React.memo
- Čiste komponente: Ko je izhod komponente odvisen samo od njenih propzov in nima lastnega stanja.
- Draga upodobitev: Ko je postopek upodobitve komponente računsko drag.
- Pogoste ponovne upodobitve: Ko se komponenta pogosto ponovno upodablja, čeprav se njeni propzi niso spremenili.
Kako deluje React.memo
React.memo
zavije funkcijsko komponento in plitvo primerja prejšnje in naslednje propze. Če so propzi enaki, se komponenta ne bo ponovno upodobila.
Primer: prikaz profila uporabnika
Ustvarimo komponento, ki prikazuje profil uporabnika. Uporabili bomo React.memo
za preprečevanje nepotrebnih ponovnih upodobitev, če se podatki uporabnika niso spremenili.
import React from 'react';
function UserProfile({ user }) {
console.log('UserProfile re-rendered'); // Demonstrates when the component re-renders
return (
Name: {user.name}
Email: {user.email}
);
}
const MemoizedUserProfile = React.memo(UserProfile, (prevProps, nextProps) => {
// Custom comparison function (optional)
return prevProps.user.id === nextProps.user.id; // Only re-render if the user ID changes
});
function App() {
const [user, setUser] = React.useState({
id: 1,
name: 'John Doe',
email: 'john.doe@example.com',
});
const updateUser = () => {
setUser({ ...user, name: 'Jane Doe' }); // Changing the name
};
return (
);
}
export default App;
V tem primeru se bo komponenta MemoizedUserProfile
ponovno upodobila le, če se propz user.id
spremeni. Tudi če se druge lastnosti objekta user
spremenijo (npr. ime ali e-poštni naslov), se komponenta ne bo ponovno upodobila, razen če je ID drugačen. Ta funkcija primerjave po meri znotraj `React.memo` omogoča natančen nadzor nad tem, kdaj se komponenta ponovno upodobi. Razmislite o platformi družbenih medijev z nenehno posodobljenimi profili uporabnikov. Brez `React.memo` bi sprememba statusa uporabnika ali slike profila povzročila popolno ponovno upodobitev komponente profila, tudi če bi osnovni podatki uporabnika ostali nespremenjeni. `React.memo` omogoča ciljane posodobitve in bistveno izboljša zmogljivost.
Kombiniranje useMemo, useCallback in React.memo
Te tri tehnike so najučinkovitejše, če se uporabljajo skupaj. useMemo
memoizira drage izračune, useCallback
memoizira funkcije, React.memo
pa memoizira komponente. Z združevanjem teh tehnik lahko znatno zmanjšate število nepotrebnih ponovnih upodobitev v vaši aplikaciji React.
Primer: kompleksna komponenta
Ustvarimo bolj kompleksno komponento, ki prikazuje, kako te tehnike združiti.
import React, { useState, useCallback, useMemo } from 'react';
function ListItem({ item, onUpdate, onDelete }) {
console.log(`ListItem ${item.id} re-rendered`); // Demonstrates when the component re-renders
return (
{item.text}
);
}
const MemoizedListItem = React.memo(ListItem);
function List({ items, onUpdate, onDelete }) {
console.log('List re-rendered'); // Demonstrates when the component re-renders
return (
{items.map((item) => (
))}
);
}
const MemoizedList = React.memo(List);
function App() {
const [items, setItems] = useState([
{ id: 1, text: 'Item 1' },
{ id: 2, text: 'Item 2' },
{ id: 3, text: 'Item 3' },
]);
const handleUpdate = useCallback((id) => {
setItems((prevItems) =>
prevItems.map((item) =>
item.id === id ? { ...item, text: `Updated ${item.text}` } : item
)
);
}, []);
const handleDelete = useCallback((id) => {
setItems((prevItems) => prevItems.filter((item) => item.id !== id));
}, []);
const memoizedItems = useMemo(() => items, [items]);
return (
);
}
export default App;
V tem primeru:
useCallback
se uporablja za memoiziranje funkcijhandleUpdate
inhandleDelete
, kar preprečuje, da bi se te ponovno ustvarile ob vsaki upodobitvi.useMemo
se uporablja za memoiziranje seznamaitems
, kar preprečuje, da bi se komponentaList
ponovno upodobila, če se referenca na seznam ni spremenila.React.memo
se uporablja za memoiziranje komponentListItem
inList
, kar preprečuje, da bi se te ponovno upodobile, če se njihovi propzi niso spremenili.
Ta kombinacija tehnik zagotavlja, da se komponente ponovno upodabljajo le, ko je to potrebno, kar vodi do znatnega izboljšanja zmogljivosti. Predstavljajte si obsežno orodje za upravljanje projektov, kjer se seznami nalog nenehno posodabljajo, brišejo in preurejajo. Brez teh optimizacij bi vsaka majhna sprememba seznama nalog sprožila plaz ponovnih upodobitev, zaradi česar bi bila aplikacija počasna in neodzivna. Z strateško uporabo useMemo
, useCallback
in React.memo
lahko aplikacija ostane zmogljiva tudi s kompleksnimi podatki in pogostimi posodobitvami.
Dodatne tehnike optimizacije
Medtem ko so useMemo
, useCallback
in React.memo
zmogljiva orodja, niso edine možnosti za optimizacijo zmogljivosti React. Tukaj je nekaj dodatnih tehnik, ki jih lahko upoštevate:
- Razdelitev kode: Razdelite svojo aplikacijo na manjše dele, ki jih je mogoče naložiti na zahtevo. To zmanjša začetni čas nalaganja in izboljša splošno zmogljivost.
- Počasno nalaganje: Komponente in vire nalagajte le, ko so potrebni. To je lahko še posebej koristno za slike in druga velika sredstva.
- Virtualizacija: Upodabljajte le vidni del velikega seznama ali tabele. To lahko bistveno izboljša zmogljivost pri delu z velikimi nabori podatkov. Knjižnice, kot sta
react-window
inreact-virtualized
, lahko pomagajo pri tem. - Zmanjšanje števila klicev (Debouncing) in omejevanje (Throttling): Omejite hitrost izvajanja funkcij. To je lahko koristno pri obravnavanju dogodkov, kot sta pomikanje in spreminjanje velikosti.
- Imutabilnost: Uporabite nemutabilne podatkovne strukture, da se izognete nenamernim spremembam in poenostavite zaznavanje sprememb.
Splošne smernice za optimizacijo
Pri optimizaciji aplikacij React za globalno občinstvo je pomembno upoštevati dejavnike, kot so zakasnitev omrežja, zmogljivosti naprav in lokalizacija. Tukaj je nekaj nasvetov:
- Omrežja za dostavo vsebin (CDN): Uporabite CDN za posluževanje statičnih sredstev z lokacij, bližjih vašim uporabnikom. To zmanjša zakasnitev omrežja in izboljša čase nalaganja.
- Optimizacija slik: Optimizirajte slike za različne velikosti zaslonov in ločljivosti. Uporabite tehnike stiskanja za zmanjšanje velikosti datotek.
- Lokalizacija: Naložite samo potrebne jezikovne vire za vsakega uporabnika. To zmanjša začetni čas nalaganja in izboljša uporabniško izkušnjo.
- Prilagodljivo nalaganje: Zaznajte omrežno povezavo in zmogljivosti uporabnikove naprave ter ustrezno prilagodite vedenje aplikacije. Na primer, morda boste izklopili animacije ali zmanjšali kakovost slik za uporabnike s počasnim omrežjem ali starejšimi napravami.
Zaključek
Optimizacija zmogljivosti aplikacij React je ključnega pomena za zagotavljanje gladke in odzivne uporabniške izkušnje. Z obvladovanjem tehnik, kot so useMemo
, useCallback
in React.memo
, ter z upoštevanjem globalnih strategij optimizacije lahko ustvarite visokozmogljive aplikacije React, ki se prilagajajo potrebam raznolike uporabniške baze. Ne pozabite profilirati svoje aplikacije, da prepoznate ozka grla zmogljivosti, in te tehnike optimizacije uporabljajte strateško. Ne optimizirajte prehitro – osredotočite se na področja, kjer lahko dosežete največji vpliv.
Ta vodnik ponuja trdne temelje za razumevanje in izvajanje optimizacij zmogljivosti React. Med nadaljnjim razvojem aplikacij React ne pozabite dati prednosti zmogljivosti in nenehno iskati nove načine za izboljšanje uporabniške izkušnje.