似乎在ReactJS中的setState之后不会调用componentDidMount

Ily*_*nov 5 reactjs

学习ReactJS我正在研究一个简单的倒计时应用程序.倒计时组件如下所示:

const Countdown = React.createClass({
  getInitialState: function() {
    return {
      remaining: 10,
      running: true,
    };
  },
  componentDidMount: function(){
    if (this.state.running) {
      setInterval(this.tick, 1000);
    } else {
      console.log("already paused");
    };
  },
  tick: function(){
    if (this.state.remaining === 0) {
      this.setState({ remaining: 10 });
      this.props.updateStats();
    } else {
        this.setState({ remaining: this.state.remaining -1 });
    };

  },
  handlePauseClick: function(){
    this.setState({ running: false });
  },
  render: function(){
    const s = this.state.remaining;
    return (
      <div className='ui centered card'>
        <div className='content centered'>
          <h1>{helpers.secondsToHuman(s)}</h1>
          <ButtonControls
            handlePauseClick={this.handlePauseClick}
          />
        </div>
      </div>
    )
  },
});
Run Code Online (Sandbox Code Playgroud)

倒计时开始运行.当点击暂停按钮时,它应该停止.componentDidMount仅在运行时为true时运行计时器:

if (this.state.running) {
  setInterval(this.tick, 1000);
} else {
  console.log("already paused");
};
Run Code Online (Sandbox Code Playgroud)

处理完点击后:

this.setState({ running: false });
Run Code Online (Sandbox Code Playgroud)

我期待组件被重新渲染,并且componentDidMount将再次执行.但这并没有发生.componentDidMount似乎只运行一次.

谢谢你的想法

Lyu*_*mir 11

componentDidMount被执行一次,当阵营组件被安装到树,这就是为什么它不叫后setState.

所以你需要componentDidUpdate,这个回调在每个rerender上执行,除了初始的.对于初始的,您可能需要使用componentDidMount.

此外,您没有清除else块中的间隔,这意味着tick即使再次重新呈现组件,该功能也不会停止执行.


试试这个

componentDidMount: function() {
   this.tickInterval = setInterval(this.tick, 1000);
},

componentDidUpdate: function() {
  // if app is running and there is no tickInterval yet, set it
  if (this.state.running && this.tickInterval === null) {
    this.tickInterval = setInterval(this.tick, 1000);
  // if app is stopped, but there is a tickInterval, clear it
  } else if (!this.state.running && this.tickInterval !== null) {
    clearInterval(this.tickInterval);
    this.tickInterval = null;
  }
},

componentWillUnmount() { 
  clearInterval(this.tickInterval);
}
Run Code Online (Sandbox Code Playgroud)