Hack Frontend Community

Как работает useMemo в React и зачем он нужен

useMemo — это хук в React, который позволяет мемоизировать значение, то есть сохранить результат вычислений между рендерами, чтобы не пересчитывать его заново без необходимости.

Он особенно полезен, если вычисление ресурсоёмкое или зависит от переменных, которые редко меняются.


Зачем нужен useMemo

Реакт заново вызывает компонент при каждом ререндере, и все вычисления выполняются заново, даже если результат будет тот же. Если функция тяжёлая — это снижает производительность.

Важно:

useMemo не гарантирует кэш — он может очиститься при низком ресурсе памяти. Это подсказка для оптимизации, а не жёсткое хранилище.

Синтаксис

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • computeExpensiveValue — функция, возвращающая результат.
  • [a, b] — зависимости. Если они не изменились — React вернёт кешированное значение.

Пример: без useMemo

const App = ({ items }) => {
  const filtered = items.filter(item => item.active); // каждый рендер — новый фильтр

  return <List data={filtered} />;
};

Каждый раз при ререндере будет вызываться filter, даже если items не менялись.

Пример: с useMemo

const filtered = useMemo(() => {
  return items.filter(item => item.active);
}, [items]);

Теперь фильтрация произойдёт только если items изменится, в остальном будет возвращено кешированное значение.

useMemo vs useCallback

useCallbackuseMemo
Что возвращаетВозвращает функциюВозвращает значение
Пример() => heavyComputation()
ПрименениеИспользуется для обработчиковИспользуется для значений

Когда использовать useMemo

Хорошо использовать:

  • Для ресурсоёмких вычислений (например, sort, filter, map, reduce)
  • При передаче вычислённых значений в React.memo-компоненты
  • Когда value используется как зависимость в useEffect или useCallback

Избыточно использовать:

  • В простых компонентах без тяжёлых вычислений
  • Если результат всегда меняется при ререндере

Пример с тяжелой функцией

const expensiveCalculation = (num) => {
  for (let i = 0; i < 1e9; i++) {}
  return num * 2;
};

const App = ({ number }) => {
  const result = useMemo(() => expensiveCalculation(number), [number]);
  return <div>{result}</div>;
};

Без useMemo, expensiveCalculation будет запускаться каждый раз, даже если number не менялся. С useMemo — только при его изменении.

Вывод:

Используйте useMemo, чтобы избежать повторных вычислений при ререндере, особенно если они тяжёлые или влияют на производительность.