写一个useInterval React hook

一开始,理解React钩子可能会让人望而生畏,特别是当您遇到与时间相关的任何事情时,比如setInterval()。为了解决这些问题,您必须习惯hook的工作方式、它们的限制和潜在的变通方法。

首先,应该清楚setInterval()是一个副作用。毕竟,它没有直接绑定到组件的渲染方法。因此,我们应该在useEffect()钩子中调用它,并在卸载时使用它的返回值调用clearInterval()。为了避免创建多个间隔,可以使用钩子的第二个参数传递一个空的依赖数组([])。这导致只有在组件挂载时才会运行副作用。

React.useEffect(() => {
  let id = setInterval(callback, delay);
  return () => clearInterval(id);
}, []);

setInterval()内部的闭包只会在实例化时访问任何可用的变量和值。这意味着我们必须特别小心它的第一个参数,以确保每次interval运行时都有新的值可用。这个问题最简单的解决方案是使用useRef()钩子创建一个被React认为是可变的变量。这将允许我们在需要时访问新值

const savedCallback = React.useRef(callback);

React.useEffect(() => {
  let id = setInterval(savedCallback.current, delay);
  return () => clearInterval(id);
}, []);

使用useRef()钩子可能只是转移了问题。创建的引用的值现在需要在setInterval()中刷新。幸运的是,这是一个容易解决的问题。我们可以创建一个包装器函数,将该函数传递给setInterval()。通过这种方式,传递给setInterval()的函数将永远不会改变,但被括起来的引用的值在被调用时始终是最新的

const savedCallback = React.useRef(callback);

React.useEffect(() => {
  function tick() {
    savedCallback.current();
  }
  let id = setInterval(tick, delay);
  return () => clearInterval(id);
}, []);

最后,让我们将所有这些提取到一个自定义钩子中,以使其可重用。我们可以提取callback作为自定义钩子的参数,并将它用作附加的useEffect()钩子的唯一依赖项,该钩子将更新回调的引用。

const useInterval = (callback, delay) => {
  const savedCallback = React.useRef();

  React.useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  React.useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    let id = setInterval(tick, delay);
    return () => clearInterval(id);
  }, [delay]);
};

差不多就是这样。只要稍加努力,我们就可以为自定义钩子的参数添加延迟,并拥有一个完整的钩子版本的setInterval()。您可以找到这个钩子的最后调整的实现,以及一些用法示例

const Timer = props => {
  const [seconds, setSeconds] = React.useState(0);
  useInterval(() => {
    setSeconds(seconds + 1);
  }, 1000);

  return 

{seconds}

; }; ReactDOM.render(, document.getElementById('root'));

你可能感兴趣的:(写一个useInterval React hook)