通过 React Hooks 声明式地使用 setInterval-深蓝源码网

教程文章 2020-09-03 00:08:26 2283 阅读
导读 接触ReactHooks一定时间的你,也许会碰到一个神奇的问题:setInterval用起来没你想的简单。RyanFlorence在他的推文里面说到:不少朋友跟我提起,setInterval和hooks一起用的时候,有种蛋蛋的忧伤。老实说,这些朋友也不是胡扯。刚开始接触Hooks的时候,确实还挺让人疑惑的。但……

接触 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>;
}

(CodeSandbox 线上示例)

上述 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 的读者而准备的。


哈?!

首页
菜单
我的
搜索