【问题标题】:componentDidMount seems not to be called after setState in ReactJS在 ReactJS 中的 setState 之后似乎没有调用 componentDidMount
【发布时间】:2016-12-12 14:10:13
【问题描述】:

学习 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>
    )
  },
});

倒计时开始运行。单击暂停按钮时,它应该停止。 componentDidMount 只在 running 为 true 时才运行定时器:

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

处理点击后:

this.setState({ running: false });

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

感谢您的想法

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    componentDidMount 只执行一次,当 React 组件被挂载到树上时,这就是为什么在 setState 之后没有调用它的原因。

    所以你需要componentDidUpdate,这个回调会在每次重新渲染时执行,除了初始的。对于第一个你可能想使用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);
    }
    

    【讨论】:

    • 谢谢@leo。不知道componentDidUpdate。它仍然无法正常工作。难道是componentDidMount的间隔根本没有停止吗?
    • 我已经编辑了我的答案,请查看并尝试根据您的需要进行调整。
    • 谢谢。现在,间隔似乎是按指数方式创建的,而不是清除的。我会玩弄它。
    • 好的,再次更新了答案...但是,是的,玩玩,你已经接近了。
    • 谢谢,现在可以使用了。 if (!this.state.running) { clearInterval(this.tickInterval, 1000); } else { clearInterval(this.tickInterval, 1000); this.tickInterval = setInterval(this.tick, 1000); };
    【解决方案2】:

    componentDidMount 仅在初始渲染过程完成时执行。您应该为您的任务使用componentWillUpdatecomponentDidUpdate

    【讨论】:

      猜你喜欢
      • 2016-08-28
      • 1970-01-01
      • 2021-09-06
      • 2018-07-25
      • 1970-01-01
      • 2019-11-24
      • 1970-01-01
      • 2018-04-14
      • 2014-04-24
      相关资源
      最近更新 更多