-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* websocket透传ws实例给options里的事件 * 删除demo2 * feat: 用RAF实现useTimeout Co-authored-by: chj_damon <chjdamon@gmail.com>
- Loading branch information
Showing
10 changed files
with
275 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { renderHook } from '@testing-library/react-hooks'; | ||
import useRafTimeout from '../index'; | ||
|
||
interface ParamsObj { | ||
fn: (...arg: any) => any; | ||
delay: number | undefined; | ||
} | ||
|
||
const setUp = ({ fn, delay }: ParamsObj) => renderHook(() => useRafTimeout(fn, delay)); | ||
|
||
const FRAME_TIME = 16.7; | ||
describe('useRafTimeout', () => { | ||
beforeAll(() => { | ||
jest.useFakeTimers('modern'); | ||
}); | ||
afterAll(() => { | ||
jest.restoreAllMocks(); | ||
}); | ||
it('should be defined', () => { | ||
expect(useRafTimeout).toBeDefined(); | ||
}); | ||
|
||
it('timeout should work', () => { | ||
const callback = jest.fn(); | ||
setUp({ fn: callback, delay: FRAME_TIME }); | ||
expect(callback).not.toBeCalled(); | ||
jest.advanceTimersByTime(FRAME_TIME * 2.5); | ||
expect(callback).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('timeout should stop when delay is undefined', () => { | ||
const delay: number | undefined = undefined; | ||
const callback = jest.fn(); | ||
setUp({ fn: callback, delay }); | ||
expect(callback).not.toBeCalled(); | ||
jest.advanceTimersByTime(FRAME_TIME * 1.5); | ||
expect(callback).not.toBeCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { renderHook } from '@testing-library/react-hooks'; | ||
import useRafTimeout from '../index'; | ||
|
||
interface ParamsObj { | ||
fn: (...arg: any) => any; | ||
delay: number | undefined; | ||
} | ||
|
||
const setUp = ({ fn, delay }: ParamsObj) => renderHook(() => useRafTimeout(fn, delay)); | ||
|
||
const FRAME_TIME = 16.7; | ||
describe('useRafTimeout', () => { | ||
beforeAll(() => { | ||
jest.useFakeTimers('modern'); | ||
}); | ||
afterAll(() => { | ||
jest.restoreAllMocks(); | ||
}); | ||
it('should downgrade to setTimeout when requstAnimationFrame is undefined', () => { | ||
const _requestAnimationFrame = global.requestAnimationFrame; | ||
const _cancelAnimationFrame = global.cancelAnimationFrame; | ||
|
||
// @ts-ignore | ||
delete global.requestAnimationFrame; | ||
// @ts-ignore | ||
delete global.cancelAnimationFrame; | ||
|
||
const callback = jest.fn(); | ||
setUp({ fn: callback, delay: FRAME_TIME }); | ||
expect(callback).not.toBeCalled(); | ||
jest.advanceTimersByTime(FRAME_TIME * 1.5); | ||
expect(callback).toHaveBeenCalledTimes(1); | ||
|
||
global.requestAnimationFrame = _requestAnimationFrame; | ||
global.cancelAnimationFrame = _cancelAnimationFrame; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* title: Basic usage | ||
* desc: Execute after 2000ms. | ||
* | ||
* title.zh-CN: 基础用法 | ||
* desc.zh-CN: 在 2000ms 后执行。 | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import { useRafTimeout } from 'ahooks'; | ||
|
||
export default () => { | ||
const [count, setCount] = useState(0); | ||
|
||
useRafTimeout(() => { | ||
setCount(count + 1); | ||
}, 2000); | ||
|
||
return <div>count: {count}</div>; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* title: Advanced usage | ||
* desc: Modify the delay to realize the timer timeout change and pause. | ||
* | ||
* title.zh-CN: 进阶使用 | ||
* desc.zh-CN: 动态修改 delay 以实现定时器间隔变化与暂停。 | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import { useRafTimeout } from 'ahooks'; | ||
|
||
export default () => { | ||
const [count, setCount] = useState(0); | ||
const [delay, setDelay] = useState<number | undefined>(1000); | ||
|
||
useRafTimeout(() => { | ||
setCount(count + 1); | ||
}, delay); | ||
|
||
return ( | ||
<div> | ||
<p> count: {count} </p> | ||
<p style={{ marginTop: 16 }}> Delay: {delay} </p> | ||
<button onClick={() => setDelay((t) => (!!t ? t + 1000 : 1000))} style={{ marginRight: 8 }}> | ||
Delay + 1000 | ||
</button> | ||
<button | ||
style={{ marginRight: 8 }} | ||
onClick={() => { | ||
setDelay(1000); | ||
}} | ||
> | ||
reset Delay | ||
</button> | ||
<button | ||
onClick={() => { | ||
setDelay(undefined); | ||
}} | ||
> | ||
clear | ||
</button> | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
--- | ||
nav: | ||
path: /hooks | ||
--- | ||
|
||
# useRafTimeout | ||
|
||
A hook implements with `requestAnimationFrame` for better performance. The API is consistent with `useTimeout`. | ||
|
||
> `requestAnimationFrame` will automatically downgrade to `setTimeout` in node environment | ||
## Examples | ||
|
||
### Default usage | ||
|
||
<code src="./demo/demo1.tsx" /> | ||
|
||
### Advanced usage | ||
|
||
<code src="./demo/demo2.tsx" /> | ||
|
||
## API | ||
|
||
```typescript | ||
useRafTimeout( | ||
fn: () => void, | ||
delay?: number | undefined, | ||
); | ||
``` | ||
|
||
### Params | ||
|
||
| Property | Description | Type | | ||
|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------| | ||
| fn | The function to be executed every `delay` milliseconds. | `() => void` | | ||
| delay | The time in milliseconds, the timer should delay in between executions of the specified function. The timer will be cancelled if delay is set to `undefined`. | `number` \| `undefined` | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { useEffect } from 'react'; | ||
import useLatest from '../useLatest'; | ||
|
||
interface Handle { | ||
id: number | NodeJS.Timeout; | ||
} | ||
|
||
const setRafTimeout = function (callback: () => void, delay: number = 16.7): Handle { | ||
if (typeof requestAnimationFrame === typeof undefined) { | ||
return { | ||
id: setTimeout(callback, delay), | ||
}; | ||
} | ||
const handle: Handle = { | ||
id: 0, | ||
}; | ||
|
||
const now = Date.now; | ||
let startTime = now(); | ||
let endTime = startTime; | ||
|
||
const loop = () => { | ||
handle.id = requestAnimationFrame(loop); | ||
endTime = now(); | ||
if (endTime - startTime >= delay) { | ||
callback(); | ||
clearRafTimeout(handle); | ||
} | ||
}; | ||
handle.id = requestAnimationFrame(loop); | ||
return handle; | ||
}; | ||
|
||
function cancelAnimationFrameIsNotDefined(t: any): t is NodeJS.Timer { | ||
return typeof cancelAnimationFrame === typeof undefined; | ||
} | ||
|
||
const clearRafTimeout = function (handle: Handle) { | ||
if (cancelAnimationFrameIsNotDefined(handle.id)) { | ||
return clearTimeout(handle.id); | ||
} | ||
cancelAnimationFrame(handle.id); | ||
}; | ||
|
||
function useRafTimeout(fn: () => void, delay: number | undefined) { | ||
const fnRef = useLatest(fn); | ||
|
||
useEffect(() => { | ||
if (typeof delay !== 'number' || delay < 0) return; | ||
const timer = setRafTimeout(() => { | ||
fnRef.current(); | ||
}, delay); | ||
return () => { | ||
clearRafTimeout(timer); | ||
}; | ||
}, [delay]); | ||
} | ||
|
||
export default useRafTimeout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
--- | ||
nav: | ||
path: /hooks | ||
--- | ||
|
||
# useRafTimeout | ||
|
||
用 `requestAnimationFrame` 模拟实现 `setTimeout`,API 和 `useTimeout` 保持一致 | ||
|
||
> Node 环境下 `requestAnimationFrame` 会自动降级到 `setTimeout` | ||
## 代码演示 | ||
|
||
### 基础用法 | ||
|
||
<code src="./demo/demo1.tsx" /> | ||
|
||
### 进阶使用 | ||
|
||
<code src="./demo/demo2.tsx" /> | ||
|
||
## API | ||
|
||
```typescript | ||
useRafTimeout( | ||
fn: () => void, | ||
delay?: number | undefined, | ||
); | ||
``` | ||
|
||
### Params | ||
|
||
| 参数 | 说明 | 类型 | | ||
|---------|---------------------------------------------|-------------------------| | ||
| fn | 要定时调用的函数 | `() => void` | | ||
| delay | 间隔时间,当取值 `undefined` 时会停止计时器 | `number` \| `undefined` | |