在 React 中使用 setState 设置间隔

IT技术 javascript reactjs
2021-05-01 13:52:12

setInterval()在 React 组件中使用一个计时器,但我不确定在使用state. 我遇到了一些异步问题。

假设我的 React 组件中有一组链接可以很好地呈现和执行回调:

let links = [10, 50, 100, 500, 1000].map((num) => {
  return(
    <Link key={num} onClick={(e) => this.switchNums(num)} to={`/somePath/${num}`}>{num}</Link>
  )
})

这是switchNums()我希望它重置现有计时器的功能:

switchNums(num){
  this.stopTimer()
  this.reset(num)
}

这是startTimer(),stopTimer()reset()

startTimer(){
  if(!this.state.timerId){      
    let timerId = setInterval(()=>{
      let timer = this.state.timer + 1
      this.setState({
        timer: timer,
        timerId: timerId
      })
    }, 1000)
  }
}

stopTimer(){
  clearInterval(this.state.timerId)     
  this.setState({timerId:null})
}

reset(size){
  this.setState({
    gameOver: false,
    counter: 0,
    correct: 0,
    numbers: this.getRandomNumbers(size),
    timer: 0
  }, this.startTimer())
}

其中一个漏洞是在点击链接会迅速导致多个间隔火,尽管if病情startTimer()我猜这与setState(). 另一个错误(我认为相关)是,当我缓慢点击时,它只会每隔一次开始间隔。

任何人都可以对此有所了解吗?或者他们做了什么来规避与setState结合使用的异步问题setInterval(任何设置状态可以返回Promise的方式?),或者哪种生命周期方法最适合这种情况?

2个回答

我认为这里最大的缺陷是你state用来存储你的间隔。虽然在技术上是可行的,但我认为您没有理由真正想要这样做。

相反,只需对您的组件使用局部变量:

startTimer(){
  if(!this.timerId){     
    this.timerId = setInterval(()=>{
      //your function
    }, 1000);
  }
}

stopTimer(){
  clearInterval(this.timerId);
}

所以我认为你根本不需要state在这里使用你的计时器。您的帖子中还有一些其他与 相关的一般性问题state,我将尝试在下面回答这些问题。请记住,它们与解决您的特定问题无关。


他们做了什么来规避异步问题setState()

您可以使用一个回调来执行代码state已设置。官方文档中一部分是关于此的;这是它所说的:

第二个参数是一个可选的回调函数,一旦 setState 完成并重新渲染组件,它将被执行。

setState(nextState, callback);

哪种生命周期方法最适合这种情况?

与上述文档相同的部分继续:

通常我们建议使用 componentDidUpdate() 来代替这种逻辑。

如果您setState的函数中有多个,并且您想在特定事件之后执行特定代码,我认为您可以使用回调。对于更一般的用途,请使用上面的生命周期方法。

使用 React Hooks useStateuseEffect您可以执行以下操作:

const [timer, setTimer] = useState(1);

useEffect(() => {
  const timerId = setInterval(() => setTimer(timer + 1), 1000);

  return () => clearInterval(timerId);
});