乐趣区

关于react.js:useInterval

是从 GitHub 根底上批改而来, 这个 GitHub 上的次要代码

import {useEffect, useRef} from 'react';

type Delay = number | null;
type TimerHandler = (...args: any[]) => void;

/**
 * Provides a declarative useInterval
 *
 * @param callback - Function that will be called every `delay` ms.
 * @param delay - Number representing the delay in ms. Set to `null` to "pause" the interval.
 */

const useInterval = (callback: TimerHandler, delay: Delay) => {const savedCallbackRef = useRef<TimerHandler>();

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

  useEffect(() => {const handler = (...args: any[]) => savedCallbackRef.current!(...args);

    if (delay !== null) {const intervalId = setInterval(handler, delay);
      return () => clearInterval(intervalId);
    }
  }, [delay]);
};

export default useInterval;

这个版本其实曾经在大部分状况曾经满足了,然而我这个是在可视化大屏编辑器中的轮播表格组件应用,当大屏拖入大量轮播表格时标签页可能会无响应于是就批改成上面这个版本

import {useEffect, useRef} from 'react'

type Delay = number | null
type TimerHandler = (...args: any[]) => void

/**
 * Provides a declarative useInterval
 * https://overreacted.io/zh-hans/making-setinterval-declarative-with-react-hooks/
 * @param callback - Function that will be called every `delay` ms.
 * @param delay - Number representing the delay in ms. Set to `null` to "pause" the interval.
 */

const Index = (callback: TimerHandler, delay: Delay) => {const savedCallbackRef = useRef<TimerHandler>()

  useEffect(() => {savedCallbackRef.current = callback}, [callback])

  useEffect(() => {if (delay && delay > 10) {let timeWorker = new Worker(new URL('./worker.js', import.meta.url))
      const handler = (...args: any[]) => savedCallbackRef.current!(...args)
      timeWorker.postMessage({action: 'start', time: delay})
      timeWorker.onmessage = handler
      return () => timeWorker.terminate()
    }
  }, [delay])
}

export default Index

worker.js:

function Fn(time = 1000) {setTimeout(() => {
    // eslint-disable-next-line no-restricted-globals
    self.postMessage(time)
    Fn(time)
  }, time)
}
onmessage = function (e) {if (e.data.action === 'start') {Fn(e.data.time)
  }
}

次要是把 setInterval 改成了 worker,react 应用 worker 的话须要一个 worker-plugin

退出移动版