Отмена задач в компонентеWillUnmount

Это распространенная проблема, но я знаю, почему, и обычно могу быстро исправить.

Однако в этом случае я не могу размонтировать задачи в своем приложении ReactJS и GatsbyJS.

Приведенный ниже код прослушивает изменения Firebase auth, а with setState делает данные auth пользователей доступными в state

_initFirebase = false;

constructor(props) {
  super(props);

  this.state = {
    authUser: null
  };
}

firebaseInit = () => {
  const { firebase } = this.props;
  if (firebase && !this._initFirebase) {
    this._initFirebase = true;

    this.listener = firebase.onAuthUserListener(
      authUser => {
        localStorage.setItem('authUser', JSON.stringify(authUser));
        this.setState({ authUser });
      },
      () => {
        localStorage.removeItem('authUser');
        this.setState({ authUser: null });
      }
    );
  }
};

componentDidMount() {
  this.setState({
    authUser: JSON.parse(localStorage.getItem('authUser'))
  });

  this.firebaseInit();
}

componentDidUpdate() {
  this.firebaseInit();
}

componentWillUnmount() {
  this.listener && this.listener();
}

Вызывает ошибку в консоли

Warning: Can't perform a React state update on an unmounted component. 

This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
    in WithAuthentication (created by Context.Consumer)
    in Component (created by Layout)
    in Layout (created by SigninPage)
    in SigninPage (created by HotExportedSigninPage)
    in AppContainer (created by HotExportedSigninPage)
    in HotExportedSigninPage (created by PageRenderer)

Насколько я понимаю, у меня достаточно unmount этих setState задач внутри componentWillUnmount.

Не могли бы вы объяснить, что я мог пропустить?

Я не знаком с firebase, это this.listener действительно "отписка"? Иначе я не понимаю, почему вы бы назвали «слушателя» в крючке размонтирования

hackape 13.04.2019 07:06
this.listener вызывается из отдельного файла как firebase.onAuthUserListener.
Darren 13.04.2019 07:09
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
171
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в том, что вы пытаетесь установить состояние после срабатывания componentWillUnmount... вы не можете установить состояние в componentWillUnmount.

Решение для вашего варианта использования:

initFirebase = false;

constructor(props) {
  super(props);

  this.state = {
    authUser: null
  };
  // this prop to check component is live or not
  this.isAmAlive = false;

}



firebaseInit = () => {
  const { firebase } = this.props;
  if (firebase && !this._initFirebase) {
    this._initFirebase = true;

    this.listener = firebase.onAuthUserListener(
      authUser => {
        localStorage.setItem('authUser', JSON.stringify(authUser));
          //check component is live or not if live update the component
          if (this.isAmAlive){
             this.setState({ authUser });
           }

      },
      () => {
        localStorage.removeItem('authUser');
         //check component is live or not if live update the component
         if (this.isAmAlive){
             this.setState({ authUser : null });
         }
      }
    );
  }
};

componentDidMount() {

  this.isAmAlive =true;

  this.setState({
    authUser: JSON.parse(localStorage.getItem('authUser'))
  });

  this.firebaseInit();
}

componentDidUpdate() {
  this.firebaseInit();
}

componentWillUnmount() {
  this.isAmAlive = false;
  this.listener && this.listener();
}

Другие вопросы по теме