使用父状态的反应计时器

问题描述 投票:0回答:1

我有一个计时器组件,它是A的子组件。我正在播放和暂停作为父组件的状态值,并将其传递给子组件。

我想在播放为true时为子组件启动setTimeout,子组件将从钩子状态获得总持续时间。

[我正在使用钩子将总的Duration存储在子项中,并在useEffect中具有setTimeout函数,并且play的值为true,然后通过将初始值减1来覆盖钩子状态值。

https://stackblitz.com/edit/react-nlxodz有2个计时器,想知道在ShowTimer中执行的操作是否是一种好的方法,每次状态更新都将调用useEffect的清除函数,并且即使以下情况计时器组件也不会与ShowTimer同步它们都以10秒开始。

javascript reactjs
1个回答
0
投票

我会说不,虽然您的showTimer方法很接近,但这不是设置计时器的好方法。

setTimeout()setInterval()均为not accurate and cannot be trusted。更好的方法是使用Date.now()方法:

const App = () => {
  const [isStart, setIsStart] = React.useState(false)
  const [duration, setDuration] = React.useState(10)
        
  const handleStart = () => setIsStart(!isStart)
  
  React.useEffect(() => {
    let interval = null
    if (!isStart || duration === 0) return
    else {
      const now = Date.now() + duration * 1000
      interval = setInterval(() => {
        const secondLeft = Math.round((now - Date.now()) / 1000)
        setDuration(secondLeft)
        if (secondLeft === 0) {
          setIsStart(false)
          clearInterval(interval)
        }
      }, 1000)
    }
    console.log("Effect render, Called because duration is changes")

    return () => {
      clearInterval(interval)
      console.log("Cleanup Effect")
    }
  }, [duration, isStart])
  
  return (
    <div className="App">
      <button onClick={handleStart} style={{ marginRight: 10 }}>
        {isStart && duration > 0 ? "Pause" : "Start"}
      </button>
      <span>{duration}</span>
    </div>
  )
}

ReactDOM.render( <App /> , document.getElementById('root'))
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
© www.soinside.com 2019 - 2024. All rights reserved.