Хук оптимизации производительности 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) { // Just do nothing ... } 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.



Чат с GPT Компилятор