Skip to content

Commit

Permalink
feat(core): add useTimeout
Browse files Browse the repository at this point in the history
  • Loading branch information
wangxingkang committed Jun 11, 2024
1 parent 5434707 commit 5042097
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ export * from './useLocalStorageState'
export * from './useSessionStorageState'
export * from './useMutationObserver'
export * from './useResizeObserver'
export * from './useTimeout'

export * from '@rcuse/shared'
50 changes: 50 additions & 0 deletions packages/core/useTimeout/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { renderHook } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import { useTimeout } from '../index'

interface ParamsObj {
fn: (...arg: any) => any
delay: number | undefined
}

const setUp = ({ fn, delay }: ParamsObj) => renderHook(() => useTimeout(fn, delay))

describe('useTimeout', () => {
vi.useFakeTimers()
// eslint-disable-next-line no-restricted-globals
vi.spyOn(global, 'clearTimeout')

it('timeout should work', () => {
const callback = vi.fn()

setUp({ fn: callback, delay: 20 })

expect(callback).not.toBeCalled()
vi.advanceTimersByTime(70)
expect(callback).toHaveBeenCalledTimes(1)
})

it('timeout should stop', () => {
const callback = vi.fn()

setUp({ fn: callback, delay: undefined })
vi.advanceTimersByTime(50)
expect(callback).toHaveBeenCalledTimes(0)

setUp({ fn: callback, delay: -2 })
vi.advanceTimersByTime(50)
expect(callback).toHaveBeenCalledTimes(0)
})

it('timeout should be clear', () => {
const callback = vi.fn()

const hook = setUp({ fn: callback, delay: 20 })
expect(callback).not.toBeCalled()

hook.result.current()
vi.advanceTimersByTime(30)
expect(callback).toHaveBeenCalledTimes(0)
expect(clearTimeout).toHaveBeenCalledTimes(1)
})
})
23 changes: 23 additions & 0 deletions packages/core/useTimeout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useCallback, useEffect, useRef } from 'react'
import { isNumber } from '@rcuse/shared'
import { useMemoizedFn } from '../useMemoizedFn'

export function useTimeout(fn: (...args: any[]) => void, delay?: number) {
const timerCallback = useMemoizedFn(fn)
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)

const clear = useCallback(() => {
if (timerRef.current)
clearTimeout(timerRef.current)
}, [])

useEffect(() => {
if (!isNumber(delay) || delay < 0)
return

timerRef.current = setTimeout(timerCallback, delay)
return clear
}, [delay])

return clear
}

0 comments on commit 5042097

Please sign in to comment.