React应用程序中的setInterval

Jos*_*ose 91 javascript state settimeout reactjs

我在React仍然相当新,但我一直在慢慢地磨,我遇到了一些我坚持不懈的事情.

我正在尝试在React中构建一个"计时器"组件,说实话,我不知道我是否正确(或有效).在下面我的代码,我设置状态来返回一个对象{ currentCount: 10 },并已与玩弄componentDidMount,componentWillUnmountrender我只能得到状态,以"倒计时",从10到9.

两部分问题:我出错了什么?并且,是否有更有效的方法来使用setTimeout(而不是使用componentDidMount&componentWillUnmount)?

先感谢您.

import React from 'react';

var Clock = React.createClass({

  getInitialState: function() {
    return { currentCount: 10 };
  },

  componentDidMount: function() {
    this.countdown = setInterval(this.timer, 1000);
  },

  componentWillUnmount: function() {
    clearInterval(this.countdown);
  },

  timer: function() {
    this.setState({ currentCount: 10 });
  },

  render: function() {
    var displayCount = this.state.currentCount--;
    return (
      <section>
        {displayCount}
      </section>
    );
  }

});

module.exports = Clock;
Run Code Online (Sandbox Code Playgroud)

dot*_*tom 142

我看到你的代码有4个问题:

  • 在您的计时器方法中,您始终将当前计数设置为10
  • 您尝试在render方法中更新状态
  • 您不使用setState方法来实际更改状态
  • 您没有将intervalId存储在状态中

我们试着解决这个问题:

componentDidMount: function() {
   var intervalId = setInterval(this.timer, 1000);
   // store intervalId in the state so it can be accessed later:
   this.setState({intervalId: intervalId});
},

componentWillUnmount: function() {
   // use intervalId from the state to clear the interval
   clearInterval(this.state.intervalId);
},

timer: function() {
   // setState method is used to update the state
   this.setState({ currentCount: this.state.currentCount -1 });
},

render: function() {
    // You do not need to decrease the value here
    return (
      <section>
       {this.state.currentCount}
      </section>
    );
}
Run Code Online (Sandbox Code Playgroud)

这将导致计时器从10减少到-N.如果您希望计时器减少到0,您可以使用稍微修改的版本:

timer: function() {
   var newCount = this.state.currentCount - 1;
   if(newCount >= 0) { 
       this.setState({ currentCount: newCount });
   } else {
       clearInterval(this.state.intervalId);
   }
},
Run Code Online (Sandbox Code Playgroud)

  • 没有必要将setInterval值存储为状态的一部分,因为它不会影响渲染 (4认同)

Gre*_*icz 29

使用更新的10秒倒计时 class Clock extends Component

import React, { Component } from 'react';

class Clock extends Component {
  constructor(props){
    super(props);
    this.state = {currentCount: 10}
  }
  timer() {
    this.setState({
      currentCount: this.state.currentCount - 1
    })
    if(this.state.currentCount < 1) { 
      clearInterval(this.intervalId);
    }
  }
  componentDidMount() {
    this.intervalId = setInterval(this.timer.bind(this), 1000);
  }
  componentWillUnmount(){
    clearInterval(this.intervalId);
  }
  render() {
    return(
      <div>{this.state.currentCount}</div>
    );
  }
}

module.exports = Clock;
Run Code Online (Sandbox Code Playgroud)


Gre*_*icz 14

更新了使用Hooks的 10秒倒计时(一种新的功能建议,使您无需编写类即可使用状态和其他React功能。它们当前在React v16.7.0-alpha中)。

import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';

const Clock = () => {
    const [currentCount, setCount] = useState(10);
    const timer = () => setCount(currentCount - 1);

    useEffect(
        () => {
            if (currentCount <= 0) {
                return;
            }
            const id = setInterval(timer, 1000);
            return () => clearInterval(id);
        },
        [currentCount]
    );

    return <div>{currentCount}</div>;
};

const App = () => <Clock />;

ReactDOM.render(<App />, document.getElementById('root'));
Run Code Online (Sandbox Code Playgroud)

  • “setInterval”旨在每个“间隔”时间运行一些周期性操作。这里它被用作 setTimeout,因为它是在每个时钟周期创建的。对于时钟,最好在开始时调用 setInterval 一次。 (3认同)

Jo *_* E. 12

如果有人正在寻找实现 setInterval 的 React Hook 方法。Dan Abramov 在他的博客上谈到了这件事。如果您想阅读有关该主题的好书,包括 Class 方法,请查看它。基本上,代码是一个自定义 Hook,它将 setInterval 变成声明性的。

function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}
Run Code Online (Sandbox Code Playgroud)

为方便起见,还发布了 CodeSandbox 链接:https ://codesandbox.io/s/105x531vkq


小智 6

使用 React Hooks 管理 setInterval:

  const [seconds, setSeconds] = useState(0)

  const interval = useRef(null)

  useEffect(() => { if (seconds === 60) stopCounter() }, [seconds])

  const startCounter = () => interval.current = setInterval(() => {
    setSeconds(prevState => prevState + 1)
  }, 1000)

  const stopCounter = () => clearInterval(interval.current)
Run Code Online (Sandbox Code Playgroud)