Хук за оптимизация на производителността useMemo в React
Първият хук за оптимизация на
производителността, който ще разгледаме
- е useMemo.
Този хук помага за кеширане на резултатите от ресурсоемки операции между моментите на прерисуване на екрана и съответно може да помогне за избягване на ненужни обемни изчисления. Такова кеширане се нарича още мемоизация.
Да видим как работи това. Нека
създадем компонент с бутон и
заглавие h3:
return (
<div>
<h3>Text</h3>
<button>click</button>
</div>
);
А сега нека направим така, че при клик
върху заглавието цветът му да се променя от оранжев
на зелен и обратно. Като начало
нека създадем състояние isGreen:
const [isGreen, setIsGreen] = useState(false);
Нека добавим в атрибута style на заглавието
условие за промяна на цвета на заглавието и
да добавим манипулатор на клик:
<h3 onClick={() => setIsGreen(!isGreen)}
style={{ color: isGreen ? 'green' : 'orangered' }}
>Text</h3>
Нека имаме и някаква стойност, която ще се увеличава с единица при клик върху нашия бутон. Нека създадем за него състояние:
const [num, setNum] = useState(0);
Нека добавим обработка на клика върху бутона:
<button onClick={() => setNum(num + 1)}>
clicks
</button>
Нека имаме и някаква функция
square, която ще връща
квадрата на стойността num. Резултатът
от извикването на функцията ще записваме в
променливата result:
const result = square(num);
function square(num) {
return num * num;
}
Нека изведем result в текста на бутона:
<button onClick={() => setNum(num + 1)}>
clicks: {result}
</button>
В резултат получихме следното:
при клик на бутона се променя стойността
num, която след това се повдига
на квадрат, а при клик на заглавието
се променя цветът на заглавието.
Имаме много малък компонент, всичко работи бързо, въпреки че при клик върху заглавието за смяна на цвета му целият компонент се прерисува отново, съответно се извършват отново и изчисленията, които са свързани с бутона, и това дори при условие, че не сме го докосвали. А сега си представете, ако нашите изчисления бяха обемни и всичко се преизчисляваше отново всеки път.
Нека, леко затрудним нашата функция, сега тя ще мисли малко по-дълго. Така ще симулираме бавни изчисления:
function square(num) {
let startTime = performance.now();
while (performance.now() - startTime < 500) {
// Просто не правете нищо ...
}
return num * num;
}
Сега кликвайте върху заглавието. Получава се,
че сега поради бавната работа на функцията
square (а бутона не го докосваме)
трябва да чакаме цяла вечност, за да се
промени цветът на заглавието!
Тук на помощ идва хукът
useMemo. За целта, трябва първо
да подадем функция, която изчислява
стойността, която искаме да кешираме,
тази функция трябва да е чиста и да не
приема параметри. А втори
параметър - зависимости в квадратни
скоби, с други думи, всички реактивни
стойности, които участват в кода
на функцията. Така, в result
сега ще напишем такава конструкция:
const result = useMemo(() => square(num), [num]);
Нека отново кликваме върху заглавието. Сега,
ако не докосваме бутона с изчисленията
и не променяме по този начин стойността на състоянието
num, то нищо не се преизчислява,
и React показва кешираната стойност
в бутона, затова нашето заглавие
бързо си сменя цвета.
Създайте компонент App, поставете
в него абзац. Създайте състояние text
с начална стойност 'react',
нека стойността на състоянието се показва
като текст на абзаца. Нека при клик
върху абзаца, в края на текста му се добавя
удивителен знак.
Създайте още едно състояние num, с
начална стойност 0. Поставете в
App още един абзац. Направете така,
че при клик върху него num
да се увеличава с 1.
А сега добавете в App функция
triple, която като
параметър приема num и
връща неговата утроена стойност.
Поставете резултата от извикването на функцията
в променлива result. Покажете
result като текст на втория
абзац. Кликвайте последователно на абзаците,
отбележете колко бавно се добавят
удивителните знаци.
Коригирайте ситуацията, като обвиете бавната
функция triple в useMemo.