简体   繁体   中英

Component is mounted but I can't call this.setState(…) or this.forceUpdate(…);

I am using scrollable tab view and facebook official flux solution. There are cases when a scene remains inactive (is not current selected tab) and receive a event from the store that need to update the scene, but I have this error : Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op.

I've double checked, and componentWillUnmount() is not being called .. but I receive this warning and I can't more update the state of component.

Here I have some sample code of the component that has this problem being in the unselected tab:

 constructor(props) {
    super(props);

    this.state = {
      isFavorite: this.isCurrentPostFavorite,
      isMounted: false,
      value: 0,
    };

    this.updateStateForFavoriteModification = this.updateStateForFavoriteModification.bind(this);
  }

  componentDidMount() {
    this.setState({isMounted: true});
    console.log('Article Scene did mount for article: '.toUpperCase() + this.props.sceneInfo.article.name);
    HotelStore.bind(HotelEvent.didModifiedFavorite, this.updateStateForFavoriteModification.bind(this));
  }

  componentWillUnmount() {
    this.setState({isMounted: false});
    console.log('Article Scene will unmount for article: '.toUpperCase() + this.props.sceneInfo.article.name);
    HotelStore.unbind(HotelEvent.didModifiedFavorite, this.updateStateForFavoriteModification);
  }

  changeFavoriteStatus() {
    if (this.state.isFavorite) {
      sendAction(HotelAction.removeFavorite, this.props.sceneInfo.article);
    }
    else {
      sendAction(HotelAction.addFavorite, this.props.sceneInfo.article);
    }
  }

  updateStateForFavoriteModification() {
    console.log('Update: '.toUpperCase() + this.props.sceneInfo.article.name);
    console.log('isMounted: '.toUpperCase() + this.state.isMounted);

    //
    //
    // Here I Get the error
    this.setState({isFavorite: this.isCurrentPostFavorite});
  }

  get isCurrentPostFavorite() {
    let matchNumber = HotelStore.favoritesPosts.filter((el: Post) => {
      return el.translationId === this.props.sceneInfo.article.translationId;
    }).length;
    let isFavorite = matchNumber > 0;
    console.log(isFavorite);
    return isFavorite;
  }

As result component did mount log console.log('Article Scene will unmount for article: '.toUpperCase() + this.props.sceneInfo.article.name); is never shown before updating state, also before this.setState(...) the bool isMounted is always true in the log.

EDIT : I know about isMounted and that's an antipatern, I've used this only to inspect in logs if the component is mounted or not, If I remove isMounted logic the error still persist.

First of all, you shouldn't want to check if your component is mounted or not, it's an antipattern .

I guess the warning appears because you are using setState in componentWillUnmount. I think that the problem with this is that setState is asynchronous , so the state might not be changed inmediately when you call the function.. In this case, it might try to change the state when the component is already unmounted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM