Очистка эффекта

Разбираем функцию очистки — как убрать за собой таймеры и подписки, чтобы не плодить утечки.

Функция очистки — функция, которую возвращает эффект; React вызывает её перед повторным запуском эффекта и при удалении компонента.

Проблема: эффект, который надо отменять

Некоторые эффекты «оставляют след»: запущенный таймер, подписка на событие, открытое соединение. Если компонент исчезнет, а таймер останется тикать — это утечка ресурсов. Покажем таймер:

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setSeconds((prev) => prev + 1);
    }, 1000);

    return () => clearInterval(id); // ← очистка
  }, []);

  return <p>Прошло секунд: {seconds}</p>;
}

Эффект запускает setInterval и возвращает функцию, которая его останавливает. Когда компонент исчезнет с экрана, React вызовет эту функцию и таймер не повиснет в памяти.

Когда вызывается очистка

Очистка срабатывает в двух случаях:

  1. Перед повторным запуском эффекта (если изменилась зависимость) — чтобы убрать предыдущую версию перед созданием новой.
  2. При размонтировании компонента (он исчезает с экрана).

Порядок при изменении зависимости такой: очистка старого эффекта → запуск нового. Это гарантирует, что одновременно не работают две подписки.

Пример с подпиской на событие

Классика — подписка на событие окна. Без очистки при каждой перерисовке навешивался бы новый обработчик, и их накопилось бы множество:

useEffect(() => {
  function handleResize() {
    console.log("ширина:", window.innerWidth);
  }
  window.addEventListener("resize", handleResize);

  return () => {
    window.removeEventListener("resize", handleResize); // снимаем
  };
}, []);

Что бывает без очистки

ЭффектБез очистки
setIntervalтаймер тикает после удаления компонента — утечка
addEventListenerнакапливаются дубли обработчиков
подписка на сокетлишние соединения, повторные данные

Правило

Простое правило: если эффект что-то «открывает» — он должен это «закрыть» в функции очистки. Подписался — отпишись, запустил таймер — останови, открыл соединение — закрой.

Итог

  • Эффект может вернуть функцию очистки; React вызывает её перед повтором эффекта и при удалении компонента.
  • Очистка убирает таймеры (clearInterval), подписки (removeEventListener), соединения — иначе утечки и дубли.
  • Правило: открыл ресурс в эффекте — закрой его в очистке.
Проверьте себя
1. Что должен вернуть useEffect, чтобы убрать за собой таймер или подписку?
AОбъект с настройками
BФункцию очистки
CЗначение true
DПромис
2. Когда React вызывает функцию очистки?
AТолько при ошибке
BПеред повторным запуском эффекта и при размонтировании компонента
CПосле каждого клика
DНикогда автоматически
3. Что произойдёт, если в эффекте с setInterval не сделать очистку?
AНичего, React очистит сам
BТаймер продолжит тикать после удаления компонента — утечка ресурсов
CКомпонент не отрисуется
DБудет синтаксическая ошибка
Поддержать проект