Отмена задач в компоненте WillUnmount - PullRequest
0 голосов
/ 13 апреля 2019

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

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

Приведенный ниже код прослушивает изменения Firebase auth, а с 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.

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

1 Ответ

1 голос
/ 13 апреля 2019

Проблема в том, что вы пытаетесь установить setState после срабатывания componentWillUnmount ... вы не можете установить setState в 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...