Memoizace je optimalizační technika podobná ukládání do mezipaměti. Funguje tak, že uloží předchozí výsledky volání funkce a použije tyto výsledky při příštím spuštění funkce. Je to užitečné zejména v aplikacích náročných na výpočet, které opakují volání funkcí se stejnými parametry.

Memoizaci můžete použít v prostém JavaScriptu a také v Reactu několika různými způsoby.

Memoizace v JavaScriptu

Chcete-li si zapamatovat funkci v JavaScriptu, musíte uložit výsledky této funkce do mezipaměti. Mezipaměť může být objekt s argumenty jako klíče a výsledky jako hodnoty.

Když tuto funkci zavoláte, před spuštěním nejprve zkontroluje, zda je výsledek přítomen v mezipaměti. Pokud ano, vrátí výsledky uložené v mezipaměti. V opačném případě se provede.

Zvažte tuto funkci:

funkcenáměstí(č) {
vrátit se num * num
}

Funkce přijme argument a vrátí jeho druhou mocninu.

Chcete-li funkci spustit, zavolejte ji číslem, jako je toto:

náměstí(5) // 25

S argumentem 5 bude square() běžet docela rychle. Pokud byste však spočítali druhou mocninu 70 000, došlo by ke značnému zpoždění. Ne o moc, ale se zpožděním. Nyní, pokud byste funkci zavolali vícekrát a překonali 70 000, došlo by ke zpoždění každého volání.

Toto zpoždění můžete odstranit pomocí zapamatování.

konst memoizedSquare = () => {
nechat mezipaměti = {};
vrátit se (num) => {
if (num in mezipaměti) {
console.log('Opětovné použití hodnoty uložené v mezipaměti');
vrátit se mezipaměti[č];
} jiný {
console.log('Počítání výsledku');
nechat vysledek = num * num;

// mezipaměti a Novývýsledekhodnotaprodalšíčas
mezipaměti[č] = výsledek;
vrátit se výsledek;
}
}
}

V tomto příkladu funkce zkontroluje, zda byl výsledek vypočítán dříve, tím, že zkontroluje, zda existuje v objektu mezipaměti. Pokud má, vrací již vypočtenou hodnotu.

Když funkce obdrží nové číslo, vypočítá novou hodnotu a uloží výsledky do mezipaměti, než se vrátí.

Tento příklad je opět docela jednoduchý, ale vysvětluje, jak by zapamatování fungovalo pro zlepšení výkonu programu.

Měli byste si zapamatovat pouze čisté funkce. Tyto funkce vrátí stejný výsledek, když předáte stejné argumenty. Pokud použijete zapamatování nečistých funkcí, nezlepšíte výkon, ale zvýšíte svou režii. Je to proto, že při každém uložení funkce do paměti volíte rychlost před pamětí.

Memoizace v Reactu

Pokud hledáte optimalizaci komponent Reactu, React poskytuje zapamatování pomocí háku useMemo(), React.memo a useCallBack().

Použití useMemo()

useMemo() je a Reagovat háček který přijímá funkci a pole závislostí.

konst memoizedValue = useMemo(() => computeExpensiveValue (a, b), [a, b]);

Ukládá hodnotu vrácenou z této funkce. Hodnoty v poli závislostí určují, kdy se funkce spustí. Teprve když se změní, funkce se provede znovu.

Například následující komponenta aplikace má uloženou hodnotu nazvanou výsledek.

import { useMemo } z "reagovat"
funkceAplikace(hodnota) {
konst čtverec = (hodnota) => {
vrátit se hodnota * hodnota
}
konst výsledek = useMemo(
() => čtverec (hodnota),
[hodnota]
);
vrátit se (
<div>{výsledek (5)}</div>
)
}

Komponenta App volá square() při každém vykreslení. Výkon se sníží, pokud je komponenta aplikace vykreslena mnohokrát kvůli Reagovat rekvizity změna nebo aktualizace stavu, zejména pokud je funkce square() drahá.

Protože však useMemo() ukládá vrácené hodnoty do mezipaměti, funkce square se při každém opětovném vykreslení neprovede, pokud se nezmění argumenty v poli závislostí.

Pomocí React.memo()

React.memo() je komponenta vyššího řádu, která přijímá komponentu React a funkci jako argumenty. Funkce určuje, kdy má být komponenta aktualizována.

Tato funkce je volitelná a pokud není k dispozici, React.memo provede mělké kopie porovnání aktuálních rekvizit komponenty s jejími předchozími rekvizitami. Pokud se rekvizity liší, spustí aktualizaci. Pokud jsou rekvizity stejné, přeskočí opětovné vykreslení a znovu použije uložené hodnoty.

Volitelná funkce přijímá jako argumenty předchozí a následující podpěry. Tyto rekvizity pak můžete explicitně porovnat a rozhodnout se, zda komponentu aktualizovat nebo ne.

Reagovat.memo(Komponent, [areEqual (prevProps, nextProps)])

Podívejme se nejprve na příklad bez argumentu volitelné funkce. Níže je komponenta nazvaná Komentáře, která přijímá jméno a e-mailové rekvizity.

funkceKomentáře ({jméno, komentář, lajky}) {
vrátit se (
<div>
<p>{název}</str>
<p>{komentář}</str>
<p>{lajky}</str>
</div>
)
}

Komponenta zapamatovaných komentářů bude mít React.memo zabalený takto:

konst MemoizedComment = React.memo (Komentář)

Můžete jej zavolat a poté zavolat jako kteroukoli jinou komponentu React.

<MemoizedComment name="Marie" komentář ="Pamatování je skvělé" lajky=1/>

Pokud chcete provést porovnání rekvizit sami, předejte následující funkci React.memo jako druhý argument.

import Reagovat z "reagovat"
funkcecheckCommentProps(prevProps, nextProps) {
vrátit se prevProps.name nextProps.name
&& prevProps.comment nextProps.comment
&& prevProps.likes nextProps.likes
}

konst MemoizedComment = React.memo (Komentáře, checkCommentProps)

Pokud checkProfileProps vrátí hodnotu true, komponenta se neaktualizuje. V opačném případě je znovu vykreslen.

Vlastní funkce je užitečná, když chcete upravit vykreslení. Můžete jej například použít k aktualizaci komponenty Komentáře pouze tehdy, když se změní počet lajků.

Na rozdíl od háku useMemo(), který si zapamatuje pouze vrácenou hodnotu funkce, React.memo si zapamatuje celou funkci.

Používejte React.memo pouze pro čisté komponenty. Abyste snížili náklady na porovnání, zapamatujte si pouze součásti, jejichž rekvizity se často mění.

Použití useCallBack()

K zapamatování můžete použít háček useCallBack(). funkční komponenty.

konst memoizedCallback = useCallback(
() => {
udělat něco (a, b);
},
[a, b],
);

Funkce se aktualizuje pouze tehdy, když se změní hodnoty v poli závislostí. Hák funguje jako zpětné volání useMemo(), ale zapamatuje si komponentu funkce mezi rendery namísto zapamatování hodnot.

Zvažte následující příklad zapamatované funkce, která volá rozhraní API.

import { useCallback, useEffect } z "reagovat";
konst Komponenta = () => {
konst getData = useCallback(() => {
console.log('zavolat API');
}, []);
useEffect(() => {
getData();
}, [getData]);
};

Funkce getData() volaná v useEffect bude znovu volána pouze tehdy, když se změní hodnota getData.

Měli byste si zapamatovat?

V tomto tutoriálu jste se naučili, co je memoizace, její výhody a jak ji implementovat v JavaScriptu a Reactu. Měli byste však vědět, že React je již rychlý. Ve většině případů zapamatování komponent nebo hodnot zvyšuje náklady na porovnání a nezlepšuje výkon. Z tohoto důvodu si zapamatujte pouze drahé komponenty.

React 18 také představil nové háčky jako useId, useTransition a useInsertionEffect. Můžete je použít ke zlepšení výkonu a uživatelské zkušenosti aplikací React.