> Зачем из useEffect возвращать callback и когда он вызывается (React)

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

Компании: Kodix, Aston, Сфера

Стек: React

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

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

Callback, возвращаемый из useEffect, - это функция очистки (cleanup function). Она вызывается при размонтировании компонента и перед повторным выполнением эффекта при изменении зависимостей. Это позволяет отменять подписки, таймеры, запросы и другие побочные эффекты, предотвращая утечки памяти и некорректное состояние.

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

useEffect - это хук для выполнения побочных эффектов в функциональных компонентах React. Его сигнатура: useEffect(setup, dependencies?). Первый аргумент - функция setup, которая может возвращать cleanup function. React вызывает cleanup function в двух случаях:

  1. При размонтировании компонента (componentWillUnmount).
  2. Перед повторным запуском setup, если изменились зависимости (сначала cleanup, потом setup).

Механизм основан на том, что React сохраняет ссылку на возвращённую функцию и вызывает её в нужный момент жизненного цикла. Если dependencies не указаны, cleanup вызывается только при размонтировании. Если dependencies - пустой массив, cleanup вызывается только при размонтировании, а эффект выполняется один раз. Если dependencies содержат значения, cleanup вызывается при каждом изменении любого из них перед новым запуском.

Это критически важно для корректной работы с асинхронными операциями: без cleanup старый запрос может завершиться после обновления компонента и перезаписать актуальные данные. Аналогично для подписок на внешние источники (WebSocket, ResizeObserver, scroll listeners) - без cleanup они будут накапливаться.

На практике

В реальных проектах cleanup function используется для:

  • Отмены fetch-запросов через AbortController.
  • Очистки таймеров (setTimeout, setInterval).
  • Удаления event listeners с DOM или window.
  • Отписки от WebSocket, Firebase, Redux store.
  • Сброса состояния модальных окон или анимаций при уходе со страницы.

Важно: cleanup function не должна быть async, так как React ожидает синхронную или возвращающую Promise функцию, но не обрабатывает ошибки из Promise. Если нужно выполнить асинхронную очистку, используйте синхронный код внутри cleanup.

Пример кода

JAVASCRIPT
import { useEffect, useState } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
const abortController = new AbortController();
fetch(`/api/users/${userId}`, { signal: abortController.signal })
.then(res => res.json())
.then(data => setUser(data))
.catch(err => {
if (err.name !== 'AbortError') {
console.error(err);
}
});
// cleanup function
return () => {
abortController.abort();
};
}, [userId]);
return <div>{user?.name}</div>;
}

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

Начни с чёткого определения: "это функция очистки, которая вызывается при размонтировании и перед повторным запуском эффекта". Затем объясни два сценария вызова. Приведи практический пример с AbortController или таймером. Упомяни, что без cleanup возможны race conditions и утечки памяти. Если спросят про async - объясни, почему cleanup не должна быть асинхронной. Покажи понимание жизненного цикла эффектов в React.

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

  • Понимание жизненного цикла эффектов и порядка вызова cleanup.
  • Умение предотвращать утечки памяти и race conditions.
  • Знание типичных use cases: отмена запросов, очистка таймеров, удаление listeners.
  • Понимание разницы между пустым массивом зависимостей, отсутствием массива и конкретными зависимостями.
  • Способность объяснить, почему cleanup вызывается перед повторным запуском, а не после.

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

  • Забывают возвращать cleanup, когда это необходимо (например, при подписках).
  • Пытаются сделать cleanup function async - React не ждёт Promise.
  • Используют cleanup для обновления состояния (это не её задача).
  • Путают порядок: cleanup вызывается перед новым эффектом, а не после.
  • Не учитывают, что при изменении зависимостей cleanup выполняется для старого эффекта, а новый запускается после.
  • Ошибочно полагают, что cleanup вызывается только при размонтировании, игнорируя повторные запуски.

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

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