Как отследить размонтирование функционального компонента?
Жизненный цикл
Размонтирование функционального компонента отслеживается 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 лучше отменять запрос.