首页 > 科技 > 早读《Making setInterval Declarative with React Hooks》

早读《Making setInterval Declarative with React Hooks》



https://overreacted.io/making-setinterval-declarative-with-react-hooks/

这是Dan的一篇文章,详细阐述了如何在Hooks中使用setInterval定时器(每秒递增的计数器为例),由于提取精髓,因此略有删减。

我们在 effects 中直接使用定时器会重复启动然后清除,effects 在每次渲染时都会被调用,因此我们需要一个传递一个空数组来保证它只会被调用一次,此时获取 count 新值就会很困难。

最简单处理方式是使用 state callback :

setCount((count) => count + 1)

原因 effects 是一个闭包,一直引用了第一次渲染时 count 的值,虽然 state callback 可以帮助你获取新的 state 值,但问题来了无法获取新的 props 值。

使用 useRef 来保存新的 interval 并触发回调:

const savedCallback = useRef();// 每次渲染后保存新的callback到ref中useEffect(() => {  savedCallback.current = callback;});// 只执行一次,不会被重置,在渲染后读取回调并在 interval tick 中执行它useEffect(() => {  function tick() {    savedCallback.current();  }  let id = setInterval(tick, 1000);  return () => clearInterval(id);}, []);

由于我们将 callback 保存到了 ref 中,因此解决了这个问题。

如果我们想通过参数来控制它的行为,比如暂停,重启 interval 等,假设我们的设计 delay 参数为 null 时暂停 interval ,是数值时就启动 interval,该如何做?

我们只需要在 effects 中做一点小改动:

useEffect(() => {  function tick() {    savedCallback.current();  }  if (delay !== null) {    let id = setInterval(tick, delay);    return () => clearInterval(id);  }}, [delay]);// 通过 null 来控制不创建 interval

其实通过这个 callback 案例来看,useReducer 也能解决这个问题,在 reducer 中我们可以访问到当前最新的 state 和 props ,本身 dispatch 也不会改变,所以我们可以从其中提取我们想要的。

最后结论:

我(Dan)希望这篇文章可以帮助你理解带有 setInterval() 等 API 的 Hooks 的相关常见问题、可以帮助你克服它们的模式、及享用建立在它们之上更具表达力的声明式 APIs 的甜蜜果实。

本文来自投稿,不代表本人立场,如若转载,请注明出处:http://www.souzhinan.com/kj/270461.html