← Назад к вопросам

Когда происходит вызов componentWillUnMount в React?

2.0 Middle🔥 141 комментариев
#React#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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>;
  }
}
Когда происходит вызов componentWillUnMount в React? | PrepBro