Skip to content

Commit

Permalink
feat(react): 新增 useInterval
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Jul 9, 2020
1 parent 8406d7b commit d7e942c
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/react/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

export * from 'react-use'

// @index(['./**/*.ts', '!./**/*.{test,taro}.*', '!./{useToggle,createGlobalState,useTitle}.*'], f => `export * from '${f.path}'`)
// @index(['./**/*.ts', '!./**/*.{test,taro}.*', '!./{useToggle,createGlobalState,useTitle,useInterval}.*'], f => `export * from '${f.path}'`)
export * from './useClassName'
export * from './useLoadMore'
export * from './useReachBottom'
Expand All @@ -26,3 +26,4 @@ export {
CreateGlobalStateState,
} from './createGlobalState'
export { useTitle } from './useTitle'
export { useInterval, UseIntervalResult } from './useInterval'
20 changes: 20 additions & 0 deletions src/react/useInterval.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { renderHook } from '@testing-library/react-hooks'
import { useInterval } from './useInterval'
import { wait } from '../utils'

describe('useInterval', () => {
test('表现正常', async () => {
let i = 0
const { result } = renderHook(() => useInterval(() => i++, 20))
expect(result.current[0]).toBe(0)
await wait(20)
expect(result.current[0]).toBe(1)
result.current[1].stop()
await wait(40)
expect(result.current[0]).toBe(1)
result.current[1].start()
expect(result.current[0]).toBe(2)
await wait(20)
expect(result.current[0]).toBe(3)
})
})
51 changes: 51 additions & 0 deletions src/react/useInterval.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useCallback, useEffect, useRef, useState } from 'react'
import { useLatest } from 'react-use'

export type UseIntervalResult<TResult> = [
TResult,
{
start: () => void
stop: () => void
},
]

export function useInterval<TResult>(
callback: () => TResult,
delay: number,
): UseIntervalResult<TResult> {
const [result, setResult] = useState<TResult>(callback)
const latestCallback = useLatest(callback)
const latestDelay = useLatest(delay)
const interval = useRef<any>()
const isFirst = useRef<boolean>(true)

const stop = useCallback(() => {
if (interval.current) {
clearInterval(interval.current)
}
}, [])

const start = useCallback(() => {
stop()
if (!isFirst.current) {
setResult(latestCallback.current())
}
interval.current = setInterval(() => {
setResult(latestCallback.current())
}, latestDelay.current)
}, [])

useEffect(() => {
start()
return stop
}, [delay])

useEffect(() => {
isFirst.current = false
return () => {
isFirst.current = true
}
}, [])

return [result, { start, stop }]
}

0 comments on commit d7e942c

Please sign in to comment.