这是我的自定义 React-hook。
import { useEffect, useRef } from 'react'
function useInterval({ callback, interval, delay }) {
const savedTimerId = useRef<NodeJS.Timeout>()
useEffect(() => {
const loop = () => {
const res = callback()
const nextIteration = () => {
savedTimerId.current = setTimeout(loop, interval)
}
if (res instanceof Promise) {
res.then(nextIteration)
} else {
nextIteration()
}
}
let delayedTimerId: NodeJS.Timeout
if (!delay) {
loop()
} else {
delayedTimerId = setTimeout(loop, delay)
}
return () => {
// @ts-ignore
clearTimeout(savedTimerId.current)
if (delayedTimerId) {
clearTimeout(delayedTimerId)
}
}
}, [callback, interval, delay])
}
export { useInterval }
这是单元测试
import { renderHook } from '@testing-library/react-hooks'
import { useInterval } from '../useInterval'
describe("Test scenarios for 'useInterval' hook", () => {
jest.useFakeTimers()
it("Should call 'callback' once", () => {
const callback = jest.fn()
const interval = 10000
const params = { callback, interval }
renderHook(() => useInterval(params))
expect(setTimeout).toHaveBeenCalledTimes(1)
expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), interval)
})
})
但这就是输出
Error: expect(jest.fn()).toHaveBeenCalledTimes(expected)
Expected number of calls: 1
Received number of calls: 2
我调试了这个片段。我发现在useInterval
调用之前已经触发了一些东西setTimeout
。
似乎setTimeout
已在内部调用。做错了什么?有任何想法吗?