取消componentWillUnmount中的任务

时间:2019-04-13 04:45:11

标签: javascript reactjs firebase gatsby

这是一个常见问题,但我知道为什么,并且通常可以很快解决。

但是,在这种情况下,我似乎无法卸载我的ReactJS和GatsbyJS应用程序中的任务。

下面的代码正在监听Firebase auth的变化,并且setStateauth的用户详细信息在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内已经足够setStatecomponentWillUnmount任务。

您能解释一下我可能错过的事情吗?

1 个答案:

答案 0 :(得分:1)

问题是您正在尝试在componentWillUnmount触发后设置setState ... 您无法在componentWillUnmount中设置setState。

您的用例解决方案:

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();
}