← Назад к вопросам
Как отследить размонтирование функционального компонента?
1.0 Junior🔥 121 комментариев
#React
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Отслеживание размонтирования функционального компонента
Это фундаментальный вопрос о React lifecycle. В функциональных компонентах размонтирование отслеживается через cleanup функцию в useEffect.
Основной способ: return из useEffect
import { useEffect } from 'react';
export function ChatWindow({ userId }) {
useEffect(() => {
console.log('Компонент смонтирован');
// Cleanup функция вызывается при размонтировании
return () => {
console.log('Компонент размонтирован');
// Здесь очищаем ресурсы
};
}, []); // Пустой массив зависимостей = выполнить один раз
return <div>Чат</div>;
}
Когда компонент удаляется из DOM, React вызывает cleanup функцию (return из useEffect). Это идеальное место для:
- Отписки от WebSocket
- Отмены HTTP запросов
- Удаления event listeners
- Очистки таймеров
- Освобождения памяти
Практический пример: WebSocket подписка
function LiveNotifications({ userId }) {
useEffect(() => {
const ws = new WebSocket(`wss://api.example.com/notifications/${userId}`);
ws.onmessage = (event) => {
console.log('Новое уведомление:', event.data);
};
ws.onerror = (error) => {
console.error('WebSocket ошибка:', error);
};
// Cleanup: закрыть соединение при размонтировании
return () => {
console.log('Закрываем WebSocket');
ws.close();
};
}, [userId]);
return <div>Слушаю уведомления...</div>;
}
Отмена HTTP запросов
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const abortController = new AbortController();
const fetchUser = async () => {
try {
const response = await fetch(`/api/users/${userId}`, {
signal: abortController.signal
});
const data = await response.json();
setUser(data);
} catch (error) {
if (error.name !== 'AbortError') {
console.error('Ошибка загрузки:', error);
}
} finally {
setLoading(false);
}
};
fetchUser();
// Cleanup: отменить запрос если компонент размонтирован
return () => {
abortController.abort();
};
}, [userId]);
if (loading) return <div>Загрузка...</div>;
return <div>{user?.name}</div>;
}
Очистка таймеров и интервалов
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(s => s + 1);
}, 1000);
// Cleanup: остановить интервал
return () => {
console.log('Очищаем интервал');
clearInterval(interval);
};
}, []);
return <div>{seconds} сек</div>;
}
Специальный хук для размонтирования
Можно создать кастомный хук для упрощения:
function useOnUnmount(callback) {
useEffect(() => {
return () => callback();
}, [callback]);
}
// Использование:
function MyComponent() {
useOnUnmount(() => {
console.log('Компонент размонтирован!');
});
return <div>Контент</div>;
}
Важные моменты
-
Cleanup запускается:
- При размонтировании компонента
- При изменении зависимостей (перед новым effect)
-
Зависимости имеют значение:
[] = выполнить один раз (только при монтировании)[userId] = при каждом изменении userId- Без массива = при каждом ре-рендере (обычно не нужно)`
-
Частая ошибка: забыть очистить ресурсы приводит к утечкам памяти и багам:
- WebSocket остаётся открытым
- Таймер продолжает работать
- Event listener висит в памяти
Это ключевая концепция для создания надёжных React приложений без утечек памяти и неожиданного поведения.