← Назад к вопросам

Зачем нужна мемоизация в React?

1.0 Junior🔥 241 комментариев
#React#Оптимизация и производительность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI20 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Мемоизация в React

Зачем нужна мемоизация?

По умолчанию React перерендеривает компонент и все его дочерние компоненты при каждом изменении state или props родителя. Это нормально для простых приложений, но в сложных UI это может приводить к лишним вычислениям и медленным перерисовкам. Мемоизация — это техника кэширования результатов вычислений или рендеров для пропуска повторной работы, если входные данные не изменились.

Три инструмента мемоизации в React

1. React.memo — мемоизация компонента

Оборачивает компонент и пропускает его повторный рендер, если props не изменились (shallow comparison).

const ExpensiveList = React.memo(function ExpensiveList({ items }) {
  console.log("render ExpensiveList");
  return (
    <ul>
      {items.map(item => <li key={item.id}>{item.name}</li>)}
    </ul>
  );
});

function Parent() {
  const [count, setCount] = useState(0);
  const items = [{ id: 1, name: "Item" }]; // проблема — новая ссылка каждый раз!

  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>{count}</button>
      <ExpensiveList items={items} />
    </div>
  );
}

Важно: React.memo делает поверхностное сравнение. Если передавать объекты/функции, создаваемые при каждом рендере, мемоизация не сработает.

2. useMemo — мемоизация вычисленного значения

Кэширует результат дорогостоящего вычисления между рендерами.

function FilteredList({ items, query }) {
  // Без useMemo — фильтрация при каждом рендере
  const filtered = useMemo(() => {
    return items.filter(item =>
      item.name.toLowerCase().includes(query.toLowerCase())
    );
  }, [items, query]); // пересчитывается только если items или query изменились

  return <ul>{filtered.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
}

Также useMemo используют для сохранения ссылочной стабильности объектов, передаваемых в React.memo-компоненты.

const options = useMemo(() => ({ theme: "dark", lang: "ru" }), []);
// Теперь options — одна и та же ссылка при каждом рендере

3. useCallback — мемоизация функции

Сохраняет ссылку на функцию между рендерами. Функции пересоздаются при каждом рендере, что ломает React.memo у дочерних компонентов.

function Parent() {
  const [count, setCount] = useState(0);

  // Без useCallback — новая ссылка при каждом рендере → Child всегда перерендерится
  const handleClick = useCallback(() => {
    console.log("clicked");
  }, []); // зависимостей нет — функция создаётся один раз

  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>{count}</button>
      <Child onClick={handleClick} />
    </div>
  );
}

const Child = React.memo(({ onClick }) => {
  console.log("render Child");
  return <button onClick={onClick}>Action</button>;
});

Когда применять мемоизацию?

Стоит использовать:

  • Дорогостоящие вычисления (фильтрация/сортировка больших массивов, сложные расчёты)
  • Компоненты, которые часто рендерятся без изменения props (таблицы, списки с сотнями строк)
  • Стабилизация ссылок для дочерних компонентов с React.memo
  • Колбэки, передаваемые в хуки с массивами зависимостей (useEffect, useMemo)

Не стоит применять везде:

  • Мемоизация сама по себе имеет стоимость (сравнение зависимостей + память)
  • Простые компоненты дешевле перерендерить, чем сравнивать
  • Преждевременная оптимизация ухудшает читаемость кода

React Compiler (React 19)

В React 19 появился React Compiler (ранее React Forget), который автоматически добавляет мемоизацию там, где это нужно. Цель — избавить разработчиков от ручного написания useMemo и useCallback. При его использовании ручная мемоизация становится менее необходимой.

Итог

Мемоизация нужна для предотвращения лишних рендеров и вычислений. Три инструмента решают разные задачи: React.memo — пропуск рендера компонента, useMemo — кэш вычисленного значения, useCallback — кэш ссылки на функцию. Применять следует осознанно — только там, где есть реальный перформанс-профит.