【发布时间】:2019-08-30 14:48:33
【问题描述】:
我正在尝试使用 React-Native、React Hooks、MomentJS 和 (setTimeout/setInterval) 来制作倒数计时器。无论我尝试使用哪种方法,它都失败了。问题是组件永远不会重新渲染。
我尝试遵循官方的 React Hooks 文档,一些关于 Medium 的文章,例如 The Iceberg of React Hooks,但没有任何效果。
一种可能性是它需要对 MomentJS 对象进行深度克隆,但我猜这是一种低效的方法。
这是我尝试过的可重现示例之一。
const Timer = () => {
const [time, setTime] = useState(moment.duration(30, 'seconds'))
const intervalRef = useRef()
useEffect(() => {
intervalRef.current = setTimeout(() => {
setTime(prevTime => prevTime.subtract(1, 'second'))
}, 1000)
return () => {
clearInterval(intervalRef.current)
intervalRef.current = null
}
})
return (
<View>
{time.asSeconds()}
</View>
)
【问题讨论】:
-
使用
set*()不应该改变对象(荒谬 - 在这种情况下,您甚至不需要调用setTime())。当状态/属性不改变时避免重新渲染是使 React 易于使用的基本优化之一。创建一个新的duration对象的开销可以忽略不计,您可以使用clone()快速完成。或者,您可以考虑使用number而不是moment.Duration,并在渲染时创建一个新对象。另外注意不需要intervalRef,可以保存const ref = setTimeout(...); return () => clearInterval(ref); -
这很奇怪。我一直认为,为了在状态发生变化但对象相同时不重新渲染组件,您必须将其实现为纯组件
-
状态实际上并没有改变,对对象的引用是一样的
-
@WillJenkins 在调用
setState的非功能组件中总是重新渲染。这就是为什么我很困惑,虽然现在我想它设置状态可能总是克隆状态
标签: javascript reactjs react-native react-hooks