javascript - 使用父状态反应计时器
问题描述
我有一个计时器组件,它是 A 的子组件。我将播放和暂停作为父级的状态值并将其传递给子级。
我想在 play 为真时为子组件启动一个 setTimeout,子组件将从钩子状态获得总持续时间。
我正在使用钩子将总持续时间存储在子项中,并在 useEffect 中有一个 setTimeout 函数,如果 play 的值为 true,然后通过将初始值减 1 来覆盖钩子状态值。
https://stackblitz.com/edit/react-nlxodz有 2 个计时器,想知道我在 ShowTimer 中所做的是否是一个好方法,每次状态更新都会调用 useEffect 的清理功能,而 Timer 组件是与 ShowTimer 不同步,即使它们都以 10 秒开始。
解决方案
我会说不,这不是设置计时器的好方法,尽管您的showTimer
方法很接近。
两者setTimeout()
或setInterval()
都不准确,不能被信任。更好的方法是使用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>
推荐阅读
- python - 为什么我不能索引二维 numpy.ndarray 并分配新值
- serialization - gwt autobean 的多个编码器导致 AssertionError
- oracle - 如何在同一事务中使用新 ID 进行后续插入
- javascript - 如何使用默认值解构具有空值的嵌套对象
- rest - 控制器单元测试时出现意外错误
- c# - 如何同步执行主题中的功能?
- material-ui - 不再找到 material-ui 中的模块
- android - 如何以编程方式更改 TabItem 可见性?
- python - 如何测试 AVL 树的自定义实现
- gcc - 输入 GCC 的这种显然非标准的结构包装语法是什么?