React JS setState(...):只能更新已安装或安装的组件

时间:2017-07-20 14:27:32

标签: javascript reactjs jsx

我收到此错误setState(...): Can only update a mounted or mounting component.,但我无法解决该问题。

import React, { Component } from 'react';

import Loading1 from '../images/loading1.gif';

class LoadingSpinner extends Component {
  constructor(props){
    super(props);

    this.changeState = this.changeState.bind(this);
    this.timer = this.timer.bind(this);
  }

  state = {
    loadingImg: Loading1,
    loading: true
  }

  timer(){
    var self = this;
    var startTime = new Date().getTime();
    var interval = setInterval(function () {
      if (new Date().getTime() - startTime > 3000) {
        clearInterval(interval);
        return;
      }
      self.changeState();
    }, 2000);
  }

  changeState(){
    this.setState({
      loading: false,
    })
  }

  render() {


    const topMargin = {
      marginTop: "50px"
    }


    return (
      <div className="containter" style={topMargin}>
        <center>
          {this.state.loading ? <img src={this.state.loadingImg} onLoad=    {this.timer()} alt="Loading..." /> : <h2>Unable To Find What You Are Looking     For!</h2> }
        </center>
      </div>
    );
  }
}

export default LoadingSpinner;

这是导致问题的代码。

基本上我想要它,以便在设定的时间后它会从loading1.gif变为无法找到你要找的东西。它会这样做,但它会抛出我无法摆脱的错误setState(...): Can only update a mounted or mounting component.

这就是我调用加载微调器的方法

<Tab label="Applicant Details" value="GetCasePersonal">
     {this.state.GetCasePersonal.length === 0 ? <LoadingSpinner /> :
     <div>
         <ViewPersonalDetails Case={this.state.GetCasePersonal} />
     </div>
     }
</Tab>

2 个答案:

答案 0 :(得分:3)

您不需要使用setInterval函数,您可以轻松地使用setTimeout,并且应该使用React生命周期函数来超时,而不是将其调用onLoad of image。

&#13;
&#13;
class LoadingSpinner extends React.Component {
  constructor(props){
    super(props);
    this.timeout = null;
    this.changeState = this.changeState.bind(this);
  }

  state = {
    loadingImg: '',
    loading: true
  }

  componentDidMount(){
    
    this.timeout = setTimeout( () => {
      console.log('I am changing state');
      this.changeState();
    }, 3000);
  }
  componentWillUnmount() {
     clearTimeout(this.timeout); 
  }
  changeState(){
    this.setState({
      loading: false,
    })
  }

  render() {


    const topMargin = {
      marginTop: "50px"
    }


    return (
      <div className="containter" style={topMargin}>
        <center>
          {this.state.loading ? <img src={this.state.loadingImg} alt="Loading..." /> : <h2>Unable To Find What You Are Looking     For!</h2> }
        </center>
      </div>
    );
  }
}

ReactDOM.render(<LoadingSpinner/>, document.getElementById('app'));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

这里有很好的文档 https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html

在处理此类问题时,一个好的做法是搜索facebook facebook文档。

private _isMount = false;

componentDidMount() {
  this._isMount = true;
}

componentWillUnmount()
{
    this._isMount = false;
}

timerJob()
{
    if(this._isMount == false)
        return;
    // setState
}