前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >早读《Making setInterval Declarative with React Hooks》

早读《Making setInterval Declarative with React Hooks》

作者头像
icepy
发布2019-12-18 11:39:05
6470
发布2019-12-18 11:39:05
举报
文章被收录于专栏:子曰五溪

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

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

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

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

代码语言:javascript
复制
setCount((count) => count + 1)

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

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

代码语言:javascript
复制
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 中做一点小改动:

代码语言:javascript
复制
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 的甜蜜果实。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 子曰五溪 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档