Как работает useMemo и для чего он используется?react-24

useMemo — это хук (hook) в React, предназначенный для оптимизации производительности путем мемоизации (запоминания) вычислений. Он предотвращает повторные дорогостоящие вычисления при каждом рендере, кэшируя результат между рендерами.

Базовый синтаксис

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

Где:

  • Первый аргумент — функция, возвращающая вычисляемое значение
  • Второй аргумент — массив зависимостей (как у useEffect)

Основные принципы работы

  1. Мемоизация — хук запоминает результат вычислений
  2. Зависимости — при изменении зависимостей пересчитывает значение
  3. Оптимизация — избегает лишних вычислений при одинаковых зависимостях

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

  1. Тяжелые вычисления (complex calculations):

    const sortedList = useMemo(() => {
      return largeList.sort(complexSortFunction);
    }, [largeList]);
    
  2. Оптимизация дочерних компонентов (optimizing child components):

    const childProps = useMemo(() => ({ value }), [value]);
    return <ChildComponent props={childProps} />;
    
  3. Создание объектов/массивов (object/array creation):

    const config = useMemo(() => ({
      color: theme === 'dark' ? '#fff' : '#000',
      size: 'large'
    }), [theme]);
    

Практические примеры

Пример 1: Фильтрация списка

function UserList({ users, searchQuery }) {
  const filteredUsers = useMemo(() => {
    return users.filter(user =>
      user.name.toLowerCase().includes(searchQuery.toLowerCase())
    );
  }, [users, searchQuery]);

  return <List items={filteredUsers} />;
}

Пример 2: Тяжелые математические вычисления

function ChartComponent({ dataPoints }) {
  const chartData = useMemo(() => {
    return {
      min: Math.min(...dataPoints),
      max: Math.max(...dataPoints),
      avg: dataPoints.reduce((a, b) => a + b) / dataPoints.length
    };
  }, [dataPoints]);

  return <Chart data={chartData} />;
}

Важные особенности

  1. Не гарантирует сохранение ссылки между рендерами — React может сбросить мемоизированное значение при необходимости
  2. Не для побочных эффектов — для эффектов используйте useEffect
  3. Избегайте преждевременной оптимизации — используйте только там, где есть реальные проблемы с производительностью

Сравнение с другими хуками

Хук Назначение Выполняется
useMemo Мемоизация значений Во время рендера
useEffect Побочные эффекты После рендера
useCallback Мемоизация функций Во время рендера

Распространенные ошибки

  1. Пустой массив зависимостей:

    // Плохо: значение никогда не обновится
    const value = useMemo(() => compute(a), []);
    
  2. Избыточное использование:

    // Излишне: простое вычисление не требует мемоизации
    const sum = useMemo(() => a + b, [a, b]);
    
  3. Использование для побочных эффектов:

    // Неправильно: для эффектов используйте useEffect
    useMemo(() => {
      console.log('Это эффект!');
    }, [value]);
    

Оптимизация производительности

  1. Разделение сложных вычислений:

    const partialResult1 = useMemo(() => computePart1(data), [data]);
    const partialResult2 = useMemo(() => computePart2(partialResult1), [partialResult1]);
    
  2. Комбинирование с React.memo:

    const memoizedComponent = React.memo(({ data }) => {
      const processedData = useMemo(() => process(data), [data]);
      return <ExpensiveComponent data={processedData} />;
    });
    

Резюмируем

useMemo — это мощный инструмент оптимизации в React, который следует использовать для:

  • Тяжелых вычислений, которые не должны повторяться при каждом рендере
  • Стабилизации ссылок на объекты и массивы
  • Оптимизации дочерних компонентов, зависящих от вычисляемых значений

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