PassFront
  1. PassFront
  2. База знаний
  3. Жизненный цикл

Как очистить подписку при размонтировании компонента?

Жизненный цикл

Подписка снимается в cleanup-функции того же эффекта, который её создал. React вызовет cleanup при размонтировании (и перед каждым перезапуском эффекта).

Шаблон

useEffect(() => {
  const subscription = store.subscribe(handleChange);

  return () => subscription.unsubscribe();  // отписка
}, [store]);

Подписка и отписка живут рядом, поэтому их невозможно рассинхронизировать (в классах это были два разных метода).

Разные виды подписок

// DOM-события
window.addEventListener('resize', onResize);
return () => window.removeEventListener('resize', onResize); // та же ссылка!

// WebSocket
const ws = new WebSocket(url);
return () => ws.close();

// Наблюдатели
const observer = new IntersectionObserver(cb);
observer.observe(node);
return () => observer.disconnect();

// Таймеры
const id = setInterval(tick, 1000);
return () => clearInterval(id);

Для removeEventListener обязательно передать ту же функцию: объявлять обработчик внутри эффекта. Несколько слушателей удобно снимать одним AbortController + { signal }.

Нюансы

  • С [] cleanup сработает только при размонтировании; с [deps] — ещё и перед пересозданием подписки (это правильное поведение: отписались от старого источника, подписались на новый).
  • StrictMode (dev) проверяет корректность: подписка → отписка → подписка при монтировании.
  • Забытая отписка = утечка памяти и «зомби»-обработчики, дёргающие setState удалённого компонента.

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

Возвращать из useEffect функцию, снимающую подписку: unsubscribe/removeEventListener (с той же ссылкой на обработчик)/close/disconnect/clearInterval. React вызовет её при размонтировании и перед каждым перезапуском эффекта; корректность проверяет двойное монтирование StrictMode.

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