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

Как отследить размонтирование функционального компонента?

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

Размонтирование функционального компонента отслеживается cleanup-функцией useEffect с пустым массивом зависимостей.

Способ

useEffect(() => {
  return () => {
    // выполняется при удалении компонента из дерева
    analytics.track('modal_closed');
  };
}, []);

Пустой массив гарантирует, что эффект не перезапускается, значит cleanup сработает только при размонтировании. Если указать зависимости, cleanup будет вызываться и перед каждым перезапуском эффекта.

Практическое применение

Очистка ресурсов: clearInterval, removeEventListener, socket.close(), observer.disconnect(), controller.abort(). Это и есть основная причина «отслеживать» размонтирование.

Нюансы

  • StrictMode (dev, React 18): компонент монтируется дважды (mount → unmount → mount), cleanup выполнится и без реального удаления. Код должен быть идемпотентным.
  • Cleanup замыкает значения своего рендера. Нужны «самые свежие» данные в момент размонтирования — держать их в ref и читать ref.current.
  • Флаг isMounted для проверки «жив ли компонент» перед setState — устаревший приём: правильнее отменять сам запрос (AbortController).
  • Порядок: при размонтировании cleanup'ы выполняются сверху вниз — сначала у родителя, потом у детей.

Переиспользуемый хук

const useUnmount = (fn) => {
  const fnRef = useRef(fn);
  fnRef.current = fn;
  useEffect(() => () => fnRef.current(), []);
};

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

useEffect(() => () => { ... }, []) — cleanup с пустыми deps срабатывает только при размонтировании; используется для отписок, таймеров, закрытия соединений. Помнить о двойном монтировании в StrictMode, о замыкании значений (свежие — через ref) и о том, что вместо флага isMounted лучше отменять запрос.

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