Оглавление
Что такое useMemo?
useMemo - это хук React, который позволяет кэшировать результат вычислений между рендерами.
Как правило, useMemo уменьшает объем работы, которую необходимо выполнить при данном рендере. useMemo может мемоизировать функцию и ее результат, что означает, что если входы функции не изменяются, React вернет мемоизированное значение вместо повторного вычисления, что потенциально ускорит процесс рендеринга.
Простое объяснение
Допустим, у нас есть очень медленная функция, которая занимает огромное количество времени на вычисление в процессе рендеринга:
// a really slow function...
const slowFunction = (num) => {
for (let i = 0; i < 1000000000; i++) { }
return num * 2;
}
И нам нужен результат этой slowFunction для рендеринга веб-страницы, например, переменная complexResult:
const complexResult = slowFunction(input);
<p> { complexResult } </p>
В этом случае вызов slowFunction в каждом рендере значительно замедлит работу вашего приложения. Вот здесь и пригодится useMemo.
Мы можем обернуть slowFunction внутри useMemo и предоставить массив зависимостей. Массив зависимостей используется для определения того, нужно ли пересчитывать мемоизированное значение. Если какая-либо из зависимостей изменится, useMemo пересчитает мемоизированное значение, или просто будет использовать предыдущее ”мемоизированное” значение.
Простая метафора может быть такой:
- если я решаю головоломку в первый раз, мне нужно потратить время на прохождение всех шагов, пока я не решу ее и не дам ответ.
- Если вы попросите меня решить ту же головоломку во второй раз, мне не придется проходить все шаги еще раз. Вместо этого я просто дам вам ответ прямо, потому что он уже есть в моем мозгу.
- Если вы попросите меня решить другую головоломку, мне все равно придется потратить время на прохождение всех шагов.
Вот:
- процесс решения головоломки — это slowFunction
- ответ - complexResult
- проблема головоломки — зависимость.
Как использовать UseMemo?
Прототип приведен ниже:
const cachedValue = useMemo(calculateValue, dependencies);
где
- calculateValue: Функция, вычисляющая значение, которое вы хотите кэшировать. (обычно это медленные функции)
- зависимости: Список всех реактивных значений, на которые ссылается код calculateValue.
- cachedValue: тот же результат вызова calculateValue.
Вернемся к нашему примеру, ранее мы имели:
const complexResult = slowFunction(input);
А с помощью UseMemo эту строку можно изменить на:
const complexResult = useMemo(() => {
return slowFunction(input)
}, [input])
В приведенном выше примере complexResult будет пересчитан только в том случае, если изменится зависимость ввода. Если входные данные останутся прежними, React вернет ранее мемоизированное значение, что избавит нас от необходимости снова и снова вызывать slowFunction.
Полный пример
Если вы все еще считаете эту концепцию абстрактной или вам просто нужно немного контекста для размышлений. Ниже приведен немного более сложный пример.
Без useMemo
import { useState } from "react";
const slowFunction = (num) => {
console.log("running slow double calculation...");
for (let i = 0; i < 1000000000; i++) {}
return num * 2;
};
const Demo = () => {
const [number, setNumber] = useState(0);
const [color, setColor] = useState("black");
const doubledNumber = slowFunction(number);
return (
<div>
<input
type="number"
value={number}
onChange={(e) => setNumber(e.target.value)}
/>
<button onClick={() => setColor(color === "black" ? "green" : "black")}>
Change Color!
</button>
<p style={{ color: color }}>{doubledNumber}</p>
</div>
);
};
export default Demo;
Что произошло после нажатия кнопки изменения цвета?
- setColor вызвал повторный рендеринг
- Пересчет удвоенного числа занимает много времени
- Приводит к медленному рендерингу удвоенного числа
С помощью UseMemo
import { useState, useMemo } from "react";
const slowFunction = (num) => {
console.log("running slow double calculation...");
for (let i = 0; i < 1000000000; i++) {}
return num * 2;
};
const Demo = () => {
const [number, setNumber] = useState(0);
const [color, setColor] = useState("black");
const doubledNumber = useMemo(() => {
return slowFunction(number);
}, [number]);
return (
<div>
<input
type="number"
value={number}
onChange={(e) => setNumber(e.target.value)}
/>
<button onClick={() => setColor(color === "black" ? "green" : "black")}>
Change Color!
</button>
<p style={{ color: color }}>{doubledNumber}</p>
</div>
);
};
export default Demo;
Благодаря UseMemo нам больше не придется долго ждать установки цвета после изменения номера.
Напоминание: Не используйте UseMemo повсеместно!
Причины следующие:
- Чрезмерное использование useMemo может снизить производительность и внести ненужные накладные расходы.
- Мемоизация наиболее эффективна для дорогих вычислений, которые дают одинаковый результат при одинаковых входных данных.
- Чрезмерное использование useMemo может сделать ваш код более сложным для чтения и сопровождения.
Ссылка
useMemo. React. (n.d.). Получено 25 апреля 2023 года с https://react.dev/reference/react/useMemo.