Когда происходит вызов componentWillUnMount в React?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
componentWillUnmount в React
componentWillUnmount — это lifecycle метод в React, который вызывается прямо перед удалением компонента из DOM. Это последняя стадия жизненного цикла компонента класса.
Когда вызывается componentWillUnmount
Метод вызывается в следующих ситуациях:
1. Компонент удаляется из дерева компонентов
class MyComponent extends React.Component {
componentWillUnmount() {
console.log('Компонент удаляется!');
}
render() {
return <div>Привет</div>;
}
}
class App extends React.Component {
state = { show: true };
render() {
return (
<div>
{this.state.show && <MyComponent />}
<button onClick={() => this.setState({ show: false })}>
Удалить компонент
</button>
</div>
);
}
}
Когда click на кнопку -> show становится false -> MyComponent удаляется -> вызывается componentWillUnmount
2. Страница изменяется (навигация)
class HomePage extends React.Component {
componentWillUnmount() {
console.log('Уходим со страницы Home');
}
render() {
return <h1>Главная</h1>;
}
}
class App extends React.Component {
state = { page: 'home' };
render() {
return (
<div>
{this.state.page === 'home' && <HomePage />}
{this.state.page === 'about' && <AboutPage />}
<button onClick={() => this.setState({ page: 'about' })}>
Перейти на About
</button>
</div>
);
}
}
Переход на другую страницу -> HomePage удаляется -> вызывается componentWillUnmount
3. Условный рендер элемента
class Modal extends React.Component {
componentWillUnmount() {
console.log('Модальное окно закрывается');
// Очистка
}
render() {
return <div className="modal">Содержимое</div>;
}
}
class App extends React.Component {
state = { isModalOpen: true };
render() {
return (
<div>
{this.state.isModalOpen && <Modal />}
<button onClick={() => this.setState({ isModalOpen: false })}>
Закрыть модал
</button>
</div>
);
}
}
Для чего используется componentWillUnmount
1. Очистка подписок (subscriptions)
class UserProfile extends React.Component {
componentDidMount() {
// Подписываемся на изменения пользователя
this.subscription = userStore.subscribe(this.handleUserChange);
}
componentWillUnmount() {
// ВАЖНО: отписываемся при удалении компонента
this.subscription.unsubscribe();
}
handleUserChange = (user) => {
this.setState({ user });
};
render() {
return <div>{this.state.user?.name}</div>;
}
}
Почему это важно: если не отписаться, будут утечки памяти (memory leaks)
2. Отмена таймеров и интервалов
class Timer extends React.Component {
componentDidMount() {
this.timerId = setInterval(() => {
this.setState(prev => ({ seconds: prev.seconds + 1 }));
}, 1000);
}
componentWillUnmount() {
// Отменяем интервал при удалении
clearInterval(this.timerId);
}
state = { seconds: 0 };
render() {
return <div>Прошло {this.state.seconds} секунд</div>;
}
}
Почему это важно: если не отменить, интервал продолжит выполняться даже после удаления компонента
3. Отмена сетевых запросов
class DataFetcher extends React.Component {
componentDidMount() {
// Начинаем запрос
this.controller = new AbortController();
fetch('/api/data', { signal: this.controller.signal })
.then(r => r.json())
.then(data => this.setState({ data }))
.catch(err => {
if (err.name !== 'AbortError') {
console.error(err);
}
});
}
componentWillUnmount() {
// Отменяем запрос, если компонент удален до завершения
this.controller.abort();
}
state = { data: null };
render() {
return <div>{this.state.data ? 'Данные загружены' : 'Загрузка...'}</div>;
}
}
Почему это важно: если запрос завершится после удаления компонента, произойдет ошибка Memory leak warning
4. Удаление слушателей событий
class WindowResizeHandler extends React.Component {
componentDidMount() {
window.addEventListener('resize', this.handleResize);
}
componentWillUnmount() {
// Удаляем слушатель при удалении компонента
window.removeEventListener('resize', this.handleResize);
}
handleResize = () => {
this.setState({ width: window.innerWidth });
};
state = { width: window.innerWidth };
render() {
return <div>Ширина окна: {this.state.width}px</div>;
}
}
5. Сохранение данных (например, в localStorage)
class FormComponent extends React.Component {
componentDidMount() {
// Загружаем сохраненные данные
const saved = localStorage.getItem('formData');
if (saved) {
this.setState(JSON.parse(saved));
}
}
componentWillUnmount() {
// Сохраняем данные перед удалением
localStorage.setItem('formData', JSON.stringify(this.state));
}
state = { name: '', email: '' };
render() {
return (
<form>
<input
value={this.state.name}
onChange={e => this.setState({ name: e.target.value })}
/>
</form>
);
}
}
Современный подход с хуками (useEffect cleanup)
В современном React вместо componentWillUnmount используется cleanup функция в useEffect:
function MyComponent() {
useEffect(() => {
// Код при монтировании
const timer = setInterval(() => {
console.log('Тик');
}, 1000);
// Cleanup функция (вызывается при размонтировании)
return () => {
clearInterval(timer);
console.log('Компонент удален, интервал отменен');
};
}, []); // Пустые зависимости = только при монтировании/размонтировании
return <div>Компонент</div>;
}
Эквивалент:
// Класс компонента
class MyComponent extends React.Component {
componentDidMount() {
this.timerId = setInterval(() => {
console.log('Тик');
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timerId);
console.log('Компонент удален, интервал отменен');
}
render() {
return <div>Компонент</div>;
}
}
Сравнение методов очистки
| Метод | Когда вызывается | Использование |
|---|---|---|
| componentWillUnmount | Перед удалением компонента | Класс-компоненты |
| useEffect cleanup | Когда зависимости меняются | Функциональные компоненты |
| AbortController | При отмене запроса | Fetch API |
| removeEventListener | При удалении слушателя | Event listeners |
Важные моменты
- Только для класс-компонентов: это метод класса, не для функциональных компонентов
- Последний вызов: это последний lifecycle хук, вызывается перед complete удалением
- Очистка обязательна: пропуск cleanup -> утечки памяти
- Async операции: не запускайте async код в componentWillUnmount, используйте cleanup в useEffect
- setState запрещен: вызов setState в componentWillUnmount игнорируется (компонент удаляется)
Типичная ошибка
// НЕПРАВИЛЬНО: утечка памяти
class BadComponent extends React.Component {
componentDidMount() {
this.subscription = dataStore.subscribe(() => {
this.setState({ data: dataStore.getData() });
});
// Забыли отписаться!
}
render() {
return <div>{this.state.data}</div>;
}
}
// ПРАВИЛЬНО: очистка
class GoodComponent extends React.Component {
componentDidMount() {
this.subscription = dataStore.subscribe(() => {
this.setState({ data: dataStore.getData() });
});
}
componentWillUnmount() {
// Очищаем подписку
this.subscription.unsubscribe();
}
render() {
return <div>{this.state.data}</div>;
}
}