PassFront
  1. PassFront
  2. База знаний
  3. Рендеринг и производительность

Как искать утечку памяти в React?

Рендеринг и производительность

Утечки в React-приложении почти всегда означают, что что-то удерживает ссылки на размонтированные компоненты: подписки, таймеры, замыкания, кеши.

Типичные источники

  • Слушатели событий без removeEventListener в cleanup.
  • setInterval/setTimeout без clear.
  • Открытые WebSocket/EventSource, IntersectionObserver/ResizeObserver без disconnect.
  • Подписки на сторы и внешние библиотеки без unsubscribe.
  • Растущие кеши/массивы в модульной области или ref (буферы событий, история).
  • Замыкания в долгоживущих объектах, держащие props/state старого рендера.
  • Детачед DOM-узлы, сохранённые в ref после размонтирования.

Как искать

Chrome DevTools → Performance monitor: смотрим JS heap size и DOM nodes при повторении сценария (открыть/закрыть модалку 20 раз). Растут и не падают после GC — утечка.

Memory → Heap snapshot: сделать снимок, повторить сценарий, снять второй, сравнить (Comparison): что за объекты добавились. Ищем Detached DOM tree и удерживаемые компоненты; в «Retainers» видно, кто держит ссылку (обычно ваш обработчик или таймер).

Allocation instrumentation on timeline — где именно аллоцируется растущая память.

Performance-запись с длинным сценарием: пилообразный график, у которого нижняя граница ползёт вверх, — признак утечки.

Профилактика в коде

  • Каждому эффекту с подпиской/таймером — cleanup; проверяет StrictMode (двойное монтирование в dev).
  • Отмена запросов через AbortController; флаг «не применять ответ» после размонтирования.
  • ESLint react-hooks/exhaustive-deps — уменьшает число «висячих» замыканий.
  • Не хранить неограниченно растущие структуры в модульных переменных.

Коротко для собеседования

Искать через DevTools: Performance monitor (heap и DOM nodes не падают после повторов сценария) и сравнение heap-снимков — Detached DOM trees и retainers покажут, кто держит ссылку. Причины: подписки/таймеры/обсерверы без cleanup, незакрытые сокеты, растущие кеши и замыкания. Профилактика — cleanup в каждом эффекте, AbortController, StrictMode.

Другие вопросы раздела