Урок 05

useMemo: мемоизация значений

useMemo кеширует результат вычисления и пересчитывает его только при изменении зависимостей.

Синтаксис

const result = useMemo(() => compute(a, b), [a, b]);

Функция вызовется при первом рендере и при изменении a или b.

Зачем нужен

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

function Component({ items }: { items: Item[] }) {
    const sorted = useMemo(
        () => [...items].sort((a, b) => a.price - b.price),
        [items]
    );

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

Без useMemo сортировка выполнялась бы при каждом рендере.

Когда нужен

  • Тяжёлые вычисления: сортировка, фильтрация, агрегация больших массивов
  • Стабильность ссылок: объект или массив передаётся в useEffect или в мемоизированный компонент

Когда не нужен

  • Простые вычисления: сумма двух чисел, конкатенация строк
  • Без стабильности ссылок: если объект не передаётся в зависимость
// Не нужно
const total = useMemo(() => a + b, [a, b]);

// Достаточно
const total = a + b;

Мемоизация сама по себе имеет стоимость: сохранение значения, сравнение зависимостей. Для простых вычислений это дороже, чем сам пересчёт.

Стабильность ссылок

function Parent() {
    const filters = useMemo(() => ({ status: 'active' }), []);

    return <Child filters={filters} />;
}

Без useMemo объект создаётся заново при каждом рендере, и Child перерисовывается, даже если ничего не изменилось.

Мемоизация в зависимостях

const config = useMemo(() => ({ url, method }), [url, method]);

useEffect(() => {
    fetch(config.url, { method: config.method });
}, [config]);

Без useMemo объект меняется каждый рендер, и эффект сработает бесконечно.

useMemo vs useCallback

  • useMemo — мемоизирует значение
  • useCallback — мемоизирует функцию
const value = useMemo(() => compute(a, b), [a, b]);
const fn = useCallback(() => compute(a, b), [a, b]);

Не оптимизируй преждевременно

Не оборачивай в useMemo всё подряд. Сначала напиши просто, потом, если есть проблема производительности, добавь мемоизацию. React DevTools Profiler покажет, где узкое место.

Итоги

  • useMemo кеширует значение
  • Пересчитывает при изменении зависимостей
  • Используй для тяжёлых вычислений и стабильности ссылок
  • Не для простых операций
  • Оптимизация — только при реальной проблеме