setInterval定时器count无法自增的3个解决方法(React在Hooks中如何正确使用setInterval)

问题

写一个setInterval定时器实现数字的自增,因为之前做vue开发比较多,所以按照正常的思路写了一个发现count并不会每秒自增,而是只自增一次

const [count, setCount] = useState(0)
useEffect(() => {
  const timer = setInterval(() => {
    setCount(count + 1)
  }, 1000)
  return () => clearInterval(timer)
}, [])

后面发现useEffect的第二参数传入的是一个依赖list,若传入空数组则说明任何依赖的变化都不会导致useEffect重新执行,相当于类组件里面的componentDidMount生命周期只会执行一次,count的数值一直是初始化加载是闭包的count,所以count永远是0,界面上也只会显示1。

方案一:添加依赖

既然说第二个参数加入了依赖,只要这个依赖更新,useEffect就会再次执行,那么就在第二个参数里面加上count试试,定时器更新count,导致useEffect更新,count就可以获取到最新的值了。

const [count, setCount] = useState(0)
useEffect(() => {
  const timer = setInterval(() => {
    setCount(count + 1)
  }, 1000)
  return () => clearInterval(timer)
}, [count])

界面上的count果然更新了,说明这种方式确实有效。

方案二:函数更新

在类组件里面大家都知道setState在React处理机制下是异步执行的,但是里面传入一个函数可以获取到最新的值,所以Hooks里面是不是也有这样的机制,可以试试

const [count, setCount] = useState(0)
useEffect(() => {
  const timer = setInterval(() => {
    setCount(v => v + 1)
  }, 1000)
  return () => clearInterval(timer)
}, [])

结果发现界面上的数字count会随着时间自增。

方案三:使用useRef

useRef返回一个可变的ref对象,返回的ref对象在组件的整个生命周期内保持不变。 将定时器函数提取出来,每次定时器触发时,都能取到最新到count

const intervalRef = useRef(null)
intervalRef.current = function () {
  setCount(count + 1)
}
useEffect(() => {
  const timer = setInterval(() => {
    intervalRef.current()
  }, 1000)
  return () => clearInterval(timer)
}, [])

这里为什么成功呢,是因为React在组件重新渲染后整个生命周期都会执行一次,我们在大的生命周期中定义了intervalRef.current,所以这个intervalRef.current也会一直更新,所以里面获取到的count是最新的。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容