通过 React Hooks 声明式地使用 setInterval
本文由云+社区发表
作者:dan abramov
接触 react hooks 一定时间的你,也许会碰到一个神奇的问题: setinterval
。
ryan florence 在里面说到:
不少朋友跟我提起,setinterval 和 hooks 一起用的时候,有种蛋蛋的忧伤。
老实说,这些朋友也不是胡扯。刚开始接触 hooks 的时候,确实还挺让人疑惑的。
但我认为谈不上 hooks 的毛病,而是 react 编程模型和 setinterval
之间的一种模式差异。相比类(class),hooks 更贴近 react 编程模型,使得这种差异更加突出。
虽然有点绕,但是让两者和谐相处的方法,还是有的。
本文就来探索一下,如何让 setinterval 和 hooks 和谐地玩耍,为什么是这种方式,以及这种方式给你带来了什么新能力。
声明:本文采用循序渐进的示例来解释问题。所以有一些示例虽然看起来可以有捷径可走,但是我们还是一步步来。
如果你是 hooks 新手,不太明白我在纠结啥,不妨读一下 react hooks 的和。本文假设读者已经使用 hooks 超过一个小时。
代码呢?
通过下面的方式,我们可以轻松地实现一个每秒自增的计数器:
import react, { usestate, useeffect, useref } from 'react'; function counter() { let [count, setcount] = usestate(0); useinterval(() => { // your custom logic here setcount(count + 1); }, 1000); return <h1>{count}</h1>; }
上述 useinterval
并不是内置的 react hook,而是我实现的一个自定义 hook:
import react, { usestate, useeffect, useref } from 'react'; function useinterval(callback, delay) { const savedcallback = useref(); // remember the latest callback. useeffect(() => { savedcallback.current = callback; }); // set up the interval. useeffect(() => { function tick() { savedcallback.current(); } if (delay !== null) { let id = setinterval(tick, delay); return () => clearinterval(id); } }, [delay]); }
(如果你在错过了,这里也有一个一样的 codesandbox 线上示例)
我实现的 useinterval hook 设置了一个计时器,并且在组件 unmount 的时候清理掉了。 这是通过组件生命周期上绑定 setinterval
与 clearinterval
的组合完成的。
这是一份可以在项目中随意复制粘贴的实现,你甚至可以发布到 npm 上。
不关心为什么这样实现的读者,就不用继续阅读了。下面的内容是为希望深入理解 react hooks 的读者而准备的。