> Что делает хук useEffect и как работает функция очистки в React? (React)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: ADV/web-engineering, Точка, EvApps, Домклик, IT-One, intelsy, Сбер

Стек: React

> Пример ответа

Короткий ответ

useEffect - это хук React, который выполняет побочные эффекты после рендера компонента. Он принимает callback и массив зависимостей. Callback запускается после монтирования и при изменении зависимостей. Функция очистки, возвращаемая из callback, вызывается перед размонтированием компонента или перед повторным запуском эффекта, чтобы отменить подписки, таймеры или другие ресурсы, предотвращая утечки памяти.

Подробное объяснение

useEffect синхронизирует компонент с внешними системами: API-запросами, подписками на события, таймерами, манипуляциями с DOM. Он выполняется асинхронно после того, как браузер отрисовал изменения, не блокируя UI.

Механизм работы:

  • После каждого рендера React сравнивает массив зависимостей с предыдущим.
  • Если зависимости изменились (или эффект запускается впервые), React сначала вызывает функцию очистки предыдущего эффекта (если она есть), затем выполняет текущий callback.
  • Если массив зависимостей пуст [], эффект выполняется один раз после монтирования, а очистка - при размонтировании.
  • Если зависимости не указаны, эффект запускается после каждого рендера.

Функция очистки критична для корректного управления жизненным циклом. Она должна отменять всё, что было создано в эффекте: clearInterval, removeEventListener, abort() для fetch, отписка от WebSocket. Без очистки при повторных рендерах накапливаются дублирующиеся подписки, что ведёт к утечкам памяти и багам.

На практике

В продакшене useEffect часто используют для:

  • Загрузки данных при монтировании с обработкой race conditions через флаг isCancelled или AbortController.
  • Подписки на WebSocket или EventSource с корректным закрытием соединения.
  • Интеграции с внешними библиотеками (карты, графики), где нужно инициализировать и уничтожать экземпляры.
  • Установки/снятия глобальных обработчиков событий (scroll, resize, keyboard).

Важно помнить, что useEffect не должен использоваться для вычислений, которые можно сделать во время рендера - для этого есть useMemo и useCallback.

Пример кода

JSX
import { useEffect, useState } from 'react';
function ChatRoom({ roomId }) {
const [messages, setMessages] = useState([]);
useEffect(() => {
const connection = createWebSocketConnection(roomId);
connection.on('message', (msg) => {
setMessages((prev) => [...prev, msg]);
});
// Функция очистки - закрываем соединение при смене комнаты или размонтировании
return () => {
connection.close();
};
}, [roomId]); // Эффект перезапускается только при изменении roomId
return (
<ul>
{messages.map((msg, i) => <li key={i}>{msg}</li>)}
</ul>
);
}

Как отвечать на собеседовании

Начни с краткого определения, затем объясни жизненный цикл эффекта: монтирование → обновление зависимостей → размонтирование. Подчеркни, что функция очистки гарантирует, что предыдущий эффект не влияет на новый. Приведи пример с подпиской и её отменой. Упомяни, что React вызывает очистку перед каждым повторным запуском, а не только при размонтировании. Если спросят про strict mode - объясни, что в dev-режиме эффект монтируется, очищается и монтируется снова для выявления проблем с очисткой.

Что проверяет интервьюер

  • Понимание асинхронной природы useEffect и его отличия от lifecycle-методов классов.
  • Умение корректно управлять зависимостями и избегать лишних ререндеров.
  • Знание паттернов очистки: таймеры, подписки, отмена запросов.
  • Осознание последствий отсутствия очистки: утечки памяти, дублирование запросов, stale closures.
  • Понимание работы strict mode и его влияния на эффекты.

Типичные ошибки

  • Забывают вернуть функцию очистки для подписок и таймеров, что приводит к утечкам.
  • Указывают нестабильные зависимости (объекты, функции, создаваемые при каждом рендере), вызывая бесконечные циклы.
  • Пытаются сделать эффект синхронным или использовать async/await напрямую в callback (нужно оборачивать в анонимную async-функцию).
  • Используют useEffect для вычислений, которые можно выполнить во время рендера (например, фильтрация списка).
  • Не учитывают race conditions при асинхронных запросах - ответ от старого запроса может перезаписать новые данные.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью