美文网首页
写一个useInterval React hook

写一个useInterval React hook

作者: ikonan | 来源:发表于2022-07-26 16:26 被阅读0次

    一开始,理解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 <p>{seconds}</p>;
    };
    
    ReactDOM.render(<Timer />, document.getElementById('root'));
    

    相关文章

      网友评论

          本文标题:写一个useInterval React hook

          本文链接:https://www.haomeiwen.com/subject/fdboirtx.html