Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | import { useCallback, useEffect, useRef, useState } from 'react'
import { useLatest } from 'react-use'
export type UseIntervalResult<TResult> = [
TResult | undefined,
{
start: (delay?: number, duration?: number) => void
stop: () => void
},
]
/**
* 以一定的间隔时间重复调用某函数,并返回调用结果。
*
* @param callback 回调函数
* @param delay 间隔时间(毫秒),非数字时将不调用或停止调用函数
* @param duration 持续时间(毫秒)
* @returns 返回调用结果
*/
export function useInterval<TResult>(
callback: () => TResult,
delay: any,
duration?: number,
): UseIntervalResult<TResult> {
const [result, setResult] = useState<TResult>()
const latestCallback = useLatest(callback)
const latestDelay = useLatest(delay)
const latestDuration = useLatest(duration)
const interval = useRef<any>()
const stop = useCallback(() => {
if (interval.current) {
clearInterval(interval.current)
}
}, [])
const start = useCallback((delay?: number, duration?: number) => {
stop()
delay = delay ?? latestDelay.current
duration = duration ?? latestDuration.current
if (typeof delay === 'number') {
setResult(latestCallback.current())
interval.current = setInterval(() => {
setResult(latestCallback.current())
}, delay)
}
if (typeof duration === 'number') {
setTimeout(() => {
stop()
}, duration)
}
}, [])
useEffect(() => {
start()
return stop
}, [delay])
return [result, { start, stop }]
}
|