我有一个计时器组件,它是A的子组件。我正在播放和暂停作为父组件的状态值,并将其传递给子组件。
我想在播放为true时为子组件启动setTimeout,子组件将从钩子状态获得总持续时间。
[我正在使用钩子将总的Duration存储在子项中,并在useEffect中具有setTimeout函数,并且play的值为true,然后通过将初始值减1来覆盖钩子状态值。
https://stackblitz.com/edit/react-nlxodz有2个计时器,想知道在ShowTimer中执行的操作是否是一种好的方法,每次状态更新都将调用useEffect的清除函数,并且即使以下情况计时器组件也不会与ShowTimer同步它们都以10秒开始。
我会说不,虽然您的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>