Hook pro optimalizaci výkonu useMemo v Reactu

První hook pro optimalizaci výkonu, který se podíváme - je useMemo.

Tento hook pomáhá ukládat do mezipaměti výsledky náročných operací mezi okamžiky překreslování obrazovky a podle toho může pomoci zabránit zbytečným objemným výpočtům. Takové ukládání do mezipaměti se nazývá také memoizace.

Podívejme se, jak to funguje. Pojďme vytvořit komponentu s tlačítkem a nadpisem h3:

App.jsxreturn (
  <div>
    <h3>Text</h3>
    <button>click</button>
  </div>
);

A nyní uděláme tak, aby po kliknutí na nadpis se jeho barva měnila z oranžové na zelenou a zpět. Pro začátek vytvoříme stav isGreen:

App.jsxconst [isGreen, setIsGreen] = useState(false);

Přidejme do atributu style nadpisu podmínku změny barvy nadpisu a přidáme obsluhu kliknutí:

App.jsx<h3 onClick={() => setIsGreen(!isGreen)}
  style={{ color: isGreen ? 'green' : 'orangered' }}
>Text</h3>

Nechť máme také nějakou hodnotu, která se bude zvyšovat po kliknutí na naše tlačítko o jedničku. Vytvoříme pro ni stav:

App.jsxconst [num, setNum] = useState(0);

Přidáme obsluhu kliknutí na tlačítko:

App.jsx<button onClick={() => setNum(num + 1)}>
  kliky
</button>

Nechť máme také nějakou funkci square, která bude vracet druhou mocninu hodnoty num. Výsledek volání funkce budeme zapisovat do proměnné result:

App.jsxconst result = square(num);

function square(num) {
  return num * num;
}

Vypíšeme result v textu tlačítka:

App.jsx<button onClick={() => setNum(num + 1)}>
  kliky: {result}
</button>

Výsledkem jsme dostali následující: po kliknutí na tlačítko se změní hodnota num, která se pak umocní na druhou, a po kliknutí na nadpis se změní barva nadpisu.

Máme velmi malou komponentu, vše funguje rychle, i přesto, že po kliknutí na nadpis pro změnu jeho barvy se celá komponenta vykreslí znovu, podle toho dochází znovu i k výpočtům, které jsou vázány na tlačítko, a to i při tom, že jsme se ho nedotkli. A teď si představte, kdyby naše výpočty byly objemné a vše by se přepočítávalo znovu pokaždé.

Pojďme, trochu zatížit naši funkci, nyní bude chvíli přemýšlet. Tímto způsobem nasimulujeme dlouhé výpočty:

App.jsxfunction square(num) {
  let startTime = performance.now();
  
  while (performance.now() - startTime < 500) {
    // Prostě nic nedělej ...
  }
  
  return num * num;
}

Klikejme nyní na nadpis. Vychází to tak, že nyní kvůli dlouhé práci funkce square (a tlačítko jsme se nedotkli) musíme celou věčnost čekat, aby u nadpisu změnila barva!

Zde nám na pomoc přijde hook useMemo. K tomu potřebujeme prvním parametrem předat funkci, která vypočítá hodnotu, kterou chceme uložit do mezipaměti, tato funkce musí být čistá a nesmí přijímat žádné parametry. A druhým parametrem - závislosti v hranatých závorkách, jinými slovy, všechny reaktivní hodnoty, které se účastní v kódu funkce. Tímto způsobem, do result nyní napíšeme takovou konstrukci:

App.jsxconst result = useMemo(() => square(num), [num]);

Znovu klikejme na nadpis. Nyní, pokud se nedotýkáme tlačítka s výpočty a neměníme tímto způsobem hodnotu stavu num, tak se nic nepřepočítává, a React zobrazuje hodnotu uloženou v mezipaměti v tlačítku, proto náš nadpis rychle mění svou barvu.

Задание 1

Vytvořte komponentu App, umístěte v ní odstavec. Vytvořte stav text s počáteční hodnotou 'react', nechť hodnota stavu se zobrazuje jako text odstavce. Nechť po kliknutí na odstavec, se mu na konec textu přidá vykřičník.

Задание 2

Vytvořte ještě jeden stav num, s počáteční hodnotou 0. Umístěte v App ještě jeden odstavec. Udělejte tak, aby při kliknutí na něj se num zvýšila o 1.

Задание 3

A nyní přidejte do App funkci triple, která jako parametr přijímá num a vrací jeho ztrojnásobenou hodnotu. Vložte výsledek volání funkce do proměnné result. Zobrazte result jako text druhého odstavce. Klikejte postupně na odstavce, poznamenejte si, jak pomalu se přidávají vykřičníky.

Задание 4

Opravte situaci, obalení pomalé funkce triple do useMemo.