Hrvatski

Istražite napredne tehnike memoizacije u Reactu za optimizaciju performansi globalnih aplikacija. Saznajte kada i kako koristiti React.memo, useCallback, useMemo i druge alate za izradu učinkovitih korisničkih sučelja.

React Memo: Dubinski uvid u tehnike optimizacije za globalne aplikacije

React je moćna JavaScript biblioteka za izradu korisničkih sučelja, no kako aplikacije postaju složenije, optimizacija performansi postaje ključna. Jedan od osnovnih alata u Reactovom setu za optimizaciju je React.memo. Ovaj blog post pruža sveobuhvatan vodič za razumijevanje i učinkovito korištenje React.memo i srodnih tehnika za izradu visokoperformantnih React aplikacija za globalnu publiku.

Što je React.memo?

React.memo je komponenta višeg reda (HOC) koja memoizira funkcionalnu komponentu. Jednostavnije rečeno, sprječava ponovno renderiranje komponente ako se njezini props-i nisu promijenili. Prema zadanim postavkama, vrši plitku usporedbu (shallow comparison) props-a. To može značajno poboljšati performanse, posebno za komponente koje su računski skupe za renderiranje ili koje se često ponovno renderiraju čak i kada njihovi props-i ostanu isti.

Zamislite komponentu koja prikazuje korisnički profil. Ako se podaci o korisniku (npr. ime, avatar) nisu promijenili, nema potrebe ponovno renderirati komponentu. React.memo vam omogućuje da preskočite ovo nepotrebno ponovno renderiranje, štedeći dragocjeno vrijeme obrade.

Zašto koristiti React.memo?

Evo ključnih prednosti korištenja React.memo:

Osnovna upotreba React.memo

Korištenje React.memo je jednostavno. Samo omotajte svoju funkcionalnu komponentu njime:

import React from 'react';

const MyComponent = (props) => {
 console.log('MyComponent renderiran');
 return (
 
{props.data}
); }; export default React.memo(MyComponent);

U ovom primjeru, MyComponent će se ponovno renderirati samo ako se data prop promijeni. Izjava console.log pomoći će vam provjeriti kada se komponenta zaista ponovno renderira.

Razumijevanje plitke usporedbe (Shallow Comparison)

Prema zadanim postavkama, React.memo vrši plitku usporedbu props-a. To znači da provjerava jesu li se reference na props-e promijenile, a ne same vrijednosti. Važno je to razumjeti kada radite s objektima i nizovima.

Razmotrite sljedeći primjer:

import React, { useState } from 'react';

const MyComponent = (props) => {
 console.log('MyComponent renderiran');
 return (
 
{props.data.name}
); }; const MemoizedComponent = React.memo(MyComponent); const App = () => { const [user, setUser] = useState({ name: 'John', age: 30 }); const handleClick = () => { setUser({ ...user }); // Stvaranje novog objekta s istim vrijednostima }; return (
); }; export default App;

U ovom slučaju, iako vrijednosti objekta user (name i age) ostaju iste, funkcija handleClick svaki put kada se pozove stvara novu referencu na objekt. Stoga će React.memo vidjeti da se data prop promijenio (jer je referenca objekta drugačija) i ponovno će renderirati MyComponent.

Prilagođena funkcija za usporedbu

Kako bi se riješio problem plitke usporedbe s objektima i nizovima, React.memo omogućuje da pružite prilagođenu funkciju za usporedbu kao drugi argument. Ova funkcija prima dva argumenta: prevProps i nextProps. Trebala bi vratiti true ako se komponenta *ne* bi trebala ponovno renderirati (tj. props-i su zapravo isti) i false ako bi se trebala ponovno renderirati.

Evo kako možete koristiti prilagođenu funkciju za usporedbu u prethodnom primjeru:

import React, { useState, memo } from 'react';

const MyComponent = (props) => {
 console.log('MyComponent renderiran');
 return (
 
{props.data.name}
); }; const areEqual = (prevProps, nextProps) => { return prevProps.data.name === nextProps.data.name && prevProps.data.age === nextProps.data.age; }; const MemoizedComponent = memo(MyComponent, areEqual); const App = () => { const [user, setUser] = useState({ name: 'John', age: 30 }); const handleClick = () => { setUser({ ...user }); }; return (
); }; export default App;

U ovom ažuriranom primjeru, funkcija areEqual uspoređuje svojstva name i age objekata user. Komponenta MemoizedComponent sada će se ponovno renderirati samo ako se promijeni ili name ili age.

Kada koristiti React.memo

React.memo je najučinkovitiji u sljedećim scenarijima:

Međutim, važno je napomenuti da React.memo nije čarobno rješenje. Neselektivna upotreba može zapravo naštetiti performansama jer i sama plitka usporedba ima svoju cijenu. Stoga je ključno profilirati vašu aplikaciju i identificirati komponente koje bi najviše profitirale od memoizacije.

Alternative za React.memo

Iako je React.memo moćan alat, nije jedina opcija za optimizaciju performansi React komponenata. Evo nekih alternativa i komplementarnih tehnika:

1. PureComponent

Za klasne komponente, PureComponent pruža sličnu funkcionalnost kao React.memo. Vrši plitku usporedbu i props-a i state-a te se ponovno renderira samo ako postoje promjene.

import React from 'react';

class MyComponent extends React.PureComponent {
 render() {
 console.log('MyComponent renderiran');
 return (
 
{this.props.data}
); } } export default MyComponent;

PureComponent je praktična alternativa ručnoj implementaciji shouldComponentUpdate, što je bio tradicionalni način sprječavanja nepotrebnih ponovnih renderiranja u klasnim komponentama.

2. shouldComponentUpdate

shouldComponentUpdate je metoda životnog ciklusa u klasnim komponentama koja vam omogućuje definiranje prilagođene logike za određivanje treba li se komponenta ponovno renderirati. Pruža najveću fleksibilnost, ali zahtijeva i više ručnog rada.

import React from 'react';

class MyComponent extends React.Component {
 shouldComponentUpdate(nextProps, nextState) {
 return nextProps.data !== this.props.data;
 }

 render() {
 console.log('MyComponent renderiran');
 return (
 
{this.props.data}
); } } export default MyComponent;

Iako je shouldComponentUpdate i dalje dostupan, PureComponent i React.memo se općenito preferiraju zbog svoje jednostavnosti i lakoće korištenja.

3. useCallback

useCallback je React hook koji memoizira funkciju. Vraća memoiziranu verziju funkcije koja se mijenja samo ako se promijenila jedna od njezinih ovisnosti. Ovo je posebno korisno za prosljeđivanje povratnih poziva (callbacks) kao props-a memoiziranim komponentama.

Razmotrite sljedeći primjer:

import React, { useState, useCallback, memo } from 'react';

const MyComponent = (props) => {
 console.log('MyComponent renderiran');
 return (
 
 );
};

const MemoizedComponent = memo(MyComponent);

const App = () => {
 const [count, setCount] = useState(0);

 const handleClick = useCallback(() => {
 setCount(count + 1);
 }, [count]);

 return (
 

Brojač: {count}

); }; export default App;

U ovom primjeru, useCallback osigurava da se funkcija handleClick mijenja samo kada se promijeni stanje count. Bez useCallback, nova funkcija bi se stvarala pri svakom renderiranju komponente App, uzrokujući nepotrebno ponovno renderiranje MemoizedComponent.

4. useMemo

useMemo je React hook koji memoizira vrijednost. Vraća memoiziranu vrijednost koja se mijenja samo ako se promijenila jedna od njezinih ovisnosti. Ovo je korisno za izbjegavanje skupih izračuna koje nije potrebno ponovno pokretati pri svakom renderiranju.

import React, { useState, useMemo } from 'react';

const App = () => {
 const [input, setInput] = useState('');

 const expensiveCalculation = (str) => {
 console.log('Izračunavanje...');
 let result = 0;
 for (let i = 0; i < str.length * 1000000; i++) {
 result++;
 }
 return result;
 };

 const memoizedResult = useMemo(() => expensiveCalculation(input), [input]);

 return (
 
setInput(e.target.value)} />

Rezultat: {memoizedResult}

); }; export default App;

U ovom primjeru, useMemo osigurava da se funkcija expensiveCalculation poziva samo kada se promijeni stanje input. To sprječava ponovno pokretanje izračuna pri svakom renderiranju, što može značajno poboljšati performanse.

Praktični primjeri za globalne aplikacije

Razmotrimo neke praktične primjere kako se React.memo i srodne tehnike mogu primijeniti u globalnim aplikacijama:

1. Birač jezika

Komponenta za odabir jezika često renderira popis dostupnih jezika. Popis može biti relativno statičan, što znači da se ne mijenja često. Korištenje React.memo može spriječiti nepotrebno ponovno renderiranje birača jezika kada se ažuriraju drugi dijelovi aplikacije.

import React, { memo } from 'react';

const LanguageItem = ({ language, onSelect }) => {
 console.log(`LanguageItem ${language} renderiran`);
 return (
 
  • onSelect(language)}>{language}
  • ); }; const MemoizedLanguageItem = memo(LanguageItem); const LanguageSelector = ({ languages, onSelect }) => { return (
      {languages.map((language) => ( ))}
    ); }; export default LanguageSelector;

    U ovom primjeru, MemoizedLanguageItem će se ponovno renderirati samo ako se promijeni prop language ili onSelect. To može biti posebno korisno ako je popis jezika dugačak ili ako je rukovatelj (handler) onSelect složen.

    2. Konverter valuta

    Komponenta konvertera valuta može prikazivati popis valuta i njihove tečajeve. Tečajevi se mogu povremeno ažurirati, ali popis valuta može ostati relativno stabilan. Korištenje React.memo može spriječiti nepotrebno ponovno renderiranje popisa valuta kada se ažuriraju tečajevi.

    import React, { memo } from 'react';
    
    const CurrencyItem = ({ currency, rate, onSelect }) => {
     console.log(`CurrencyItem ${currency} renderiran`);
     return (
     
  • onSelect(currency)}>{currency} - {rate}
  • ); }; const MemoizedCurrencyItem = memo(CurrencyItem); const CurrencyConverter = ({ currencies, onSelect }) => { return (
      {Object.entries(currencies).map(([currency, rate]) => ( ))}
    ); }; export default CurrencyConverter;

    U ovom primjeru, MemoizedCurrencyItem će se ponovno renderirati samo ako se promijeni prop currency, rate ili onSelect. To može poboljšati performanse ako je popis valuta dugačak ili ako su ažuriranja tečaja česta.

    3. Prikaz korisničkog profila

    Prikazivanje korisničkog profila uključuje prikaz statičkih informacija poput imena, profilne slike i potencijalno biografije. Korištenje `React.memo` osigurava da se komponenta ponovno renderira samo kada se podaci o korisniku zaista promijene, a ne pri svakom ažuriranju roditeljske komponente.

    import React, { memo } from 'react';
    
    const UserProfile = ({ user }) => {
     console.log('UserProfile renderiran');
     return (
     

    {user.name}

    Profil

    {user.bio}

    ); }; export default memo(UserProfile);

    Ovo je posebno korisno ako je `UserProfile` dio veće, često ažurirane nadzorne ploče ili aplikacije gdje se sami podaci o korisniku ne mijenjaju često.

    Česte zamke i kako ih izbjeći

    Iako je React.memo vrijedan alat za optimizaciju, važno je biti svjestan čestih zamki i kako ih izbjeći:

    Profiliranje vaše aplikacije

    Najbolji način da utvrdite poboljšava li React.memo zaista performanse jest profiliranje vaše aplikacije. React pruža nekoliko alata za profiliranje, uključujući React DevTools Profiler i React.Profiler API.

    React DevTools Profiler omogućuje vam snimanje tragova performansi vaše aplikacije i identificiranje komponenata koje se često ponovno renderiraju. API React.Profiler omogućuje vam programsko mjerenje vremena renderiranja određenih komponenata.

    Profiliranjem vaše aplikacije možete identificirati komponente koje bi najviše profitirale od memoizacije i osigurati da React.memo zaista poboljšava performanse.

    Zaključak

    React.memo je moćan alat za optimizaciju performansi React komponenata. Sprječavanjem nepotrebnih ponovnih renderiranja, može poboljšati brzinu i odzivnost vaših aplikacija, što dovodi do boljeg korisničkog iskustva. Međutim, važno je koristiti React.memo promišljeno i profilirati vašu aplikaciju kako biste osigurali da zaista poboljšava performanse.

    Razumijevanjem koncepata i tehnika o kojima se raspravljalo u ovom blog postu, možete učinkovito koristiti React.memo i srodne tehnike za izradu visokoperformantnih React aplikacija za globalnu publiku, osiguravajući da su vaše aplikacije brze i odzivne za korisnike diljem svijeta.

    Ne zaboravite uzeti u obzir globalne čimbenike kao što su mrežna latencija i mogućnosti uređaja prilikom optimizacije vaših React aplikacija. Fokusiranjem na performanse i pristupačnost, možete stvoriti aplikacije koje pružaju izvrsno iskustvo za sve korisnike, bez obzira na njihovu lokaciju ili uređaj.

    Daljnje čitanje i resursi