Мемоизацията е техника за оптимизиране, подобна на кеширането. Той работи, като съхранява предишните резултати от извикване на функция и използва тези резултати при следващото изпълнение на функцията. Това е особено полезно в приложения, натоварени с изчисления, които повтарят извиквания на функции на едни и същи параметри.

Можете да използвате мемоизация в обикновен JavaScript, а също и в React, по няколко различни начина.

Мемоизация в JavaScript

За да запомните функция в JavaScript, трябва да съхраните резултатите от тази функция в кеш. Кешът може да бъде обект с аргументи като ключове и резултати като стойности.

Когато извикате тази функция, тя първо проверява дали резултатът присъства в кеша, преди да стартира. Ако е така, връща кешираните резултати. В противен случай се изпълнява.

Помислете за тази функция:

функцияквадрат(бр) {
връщане бр * бр
}

Функцията приема аргумент и връща неговия квадрат.

За да стартирате функцията, извикайте я с номер като този:

квадрат(5) // 25

С 5 като аргумент, square() ще работи доста бързо. Въпреки това, ако трябва да изчислите квадрат от 70 000, ще има забележимо забавяне. Не много, но все пак със закъснение. Сега, ако извикате функцията няколко пъти и преминете 70 000, ще изпитате забавяне при всяко извикване.

instagram viewer

Можете да премахнете това забавяне с помощта на мемоизация.

конст memoizedSquare = () => {
позволявам кеш памет = {};
връщане (брой) => {
ако (номер в кеш памет) {
console.log('Повторно използване на кешираната стойност');
връщане кеш памет[бр];
} друго {
console.log('Резултат от изчислението');
позволявам резултат = num * num;

// кеш памет на новрезултатстойностзаследващиявреме
кеш памет[бр] = резултат;
връщане резултат;
}
}
}

В този пример функцията проверява дали е изчислила резултата преди, като проверява дали съществува в обекта на кеша. Ако има, връща вече изчислената стойност.

Когато функцията получи ново число, тя изчислява нова стойност и съхранява резултатите в кеша, преди да се върне.

Отново този пример е доста прост, но обяснява как мемоизацията би работила за подобряване на производителността на програма.

Трябва да запомните само чисти функции. Тези функции връщат същия резултат, когато подадете същите аргументи. Ако използвате мемоизация върху нечисти функции, няма да подобрите производителността, а ще увеличите режийните си разходи. Това е така, защото избирате скоростта пред паметта всеки път, когато запомняте функция.

Мемоизация в React

Ако искате да оптимизирате компонентите на React, React осигурява мемоизация чрез куката useMemo(), React.memo и useCallBack().

Използване на useMemo()

useMemo() е a Реагирайте куката който приема функция и масив от зависимости.

конст memoizedValue = useMemo(() => computeExpensiveValue (a, b), [a, b]);

Той запомня стойността, върната от тази функция. Стойностите в масива на зависимостите диктуват кога функцията се изпълнява. Едва когато се променят, функцията се изпълнява отново.

Например, следният компонент на приложението има мемоизирана стойност, наречена резултат.

импортиране {useMemo} от "реагира"
функцияПриложение(стойност) {
конст квадрат = (стойност) => {
връщане стойност * стойност
}
конст резултат = useMemo(
() => квадрат (стойност),
[ стойност ]
);
връщане (
<див>{резултат (5)}</div>
)
}

Компонентът App извиква square() при всяко изобразяване. Производителността ще се влоши, ако компонентът на приложението се изобразява много пъти поради React подпори промяна или актуализиране на състоянието, особено ако функцията square() е скъпа.

Въпреки това, тъй като useMemo() кешира върнатите стойности, функцията square не се изпълнява при всяко повторно изобразяване, освен ако аргументите в масива на зависимости не се променят.

Използване на React.memo()

React.memo() е компонент от по-висок ред, който приема React компонент и функция като аргументи. Функцията определя кога компонентът трябва да се актуализира.

Функцията не е задължителна и ако не е предоставена, React.memo прави повърхностно сравнение на текущите пропсове на компонента с предишните му реквизити. Ако подпорите са различни, това задейства актуализация. Ако реквизитите са едни и същи, той пропуска повторното изобразяване и използва повторно запаметените стойности.

Незадължителната функция приема предишните и следващите реквизити като аргументи. След това можете изрично да сравните тези подпори, за да решите дали да актуализирате компонента или не.

Реагирайте.бележка(Компонент, [areEqual (prevProps, nextProps)])

Нека първо да разгледаме пример без незадължителния аргумент на функцията. По-долу е компонент, наречен Коментари, който приема подпорите за име и имейл.

функцияКоментари ({име, коментар, харесвания}) {
връщане (
<див>
<стр>{име}</стр>
<стр>{коментар}</стр>
<стр>{харесвания}</стр>
</div>
)
}

Компонентът за мемоизирани коментари ще има React.memo, обвит около него по следния начин:

конст MemoizedComment = React.memo (Коментар)

Можете да извикате след това да го извикате като всеки друг компонент на React.

<MemoizedComment name="Дева Мария" коментар="Мемоизацията е страхотна" харесвания=1/>

Ако искате сами да извършите сравнението на подпорите, предайте следната функция на React.memo като втори аргумент.

импортиране Реагирайте от "реагира"
функцияcheckCommentProps(prevProps, nextProps) {
връщане prevProps.name nextProps.name
&& prevProps.comment nextProps.comment
&& prevProps.likes nextProps.likes
}

конст MemoizedComment = React.memo (Коментари, checkCommentProps)

Ако checkProfileProps върне true, компонентът не се актуализира. В противен случай се изобразява отново.

Персонализираната функция е полезна, когато искате да персонализирате повторното изобразяване. Например, можете да го използвате, за да актуализирате компонента Коментари само когато броят на харесванията се промени.

За разлика от куката useMemo(), която запомня само върнатата стойност на функция, React.memo запаметява цялата функция.

Използвайте React.memo само за чисти компоненти. Освен това, за да намалите разходите за сравнение, запаметявайте само компоненти, чиито реквизити се променят често.

Използване на useCallBack()

Можете да използвате куката useCallBack() за запаметяване функционални компоненти.

конст memoizedCallback = useCallback(
() => {
направи нещо (a, b);
},
[a, b],
);

Функцията се актуализира само когато стойностите в масива на зависимости се променят. Куката работи като обратното извикване useMemo(), но мемоизира компонента на функцията между изобразяванията, вместо да мемоизира стойности.

Помислете за следния пример за мемоизирана функция, която извиква API.

импортиране {useCallback, useEffect} от "реагира";
конст Компонент = () => {
конст getData = useCallback(() => {
console.log('обадете се на API');
}, []);
useEffect(() => {
getData();
}, [getData]);
};

Функцията getData(), извикана в useEffect, ще бъде извикана отново само когато стойността на getData се промени.

Трябва ли да мемоизирате?

В този урок научихте какво е мемоизация, ползите от нея и как да я внедрите в JavaScript и React. Все пак трябва да знаете, че React вече е бърз. В повечето случаи запомнянето на компоненти или стойности добавя разходи за сравнение и не подобрява производителността. Поради това запаметявайте само скъпи компоненти.

React 18 също представи нови кукички като useId, useTransition и useInsertionEffect. Можете да ги използвате, за да подобрите производителността и потребителското изживяване на React приложенията.