Skip to content

Commit f9672f6

Browse files
JackWang032jialan
andauthored
feat: add useDebounce hooks (#454)
* feat: add useDebounce hooks --------- Co-authored-by: jialan <[email protected]>
1 parent 298b463 commit f9672f6

File tree

5 files changed

+138
-0
lines changed

5 files changed

+138
-0
lines changed

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export { default as StatusTag } from './statusTag';
3030
export { default as useWindowSwitchListener } from './switchWindow';
3131
export { default as Table } from './table';
3232
export { default as TinyTag } from './tinyTag';
33+
export { default as useDebounce } from './useDebounce';
3334
export { default as useIntersectionObserver } from './useIntersectionObserver';
3435
export { default as useList } from './useList';
3536
export { default as useModal } from './useModal';
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { renderHook } from '@testing-library/react-hooks';
2+
3+
import useDebounce from '..';
4+
5+
describe('test useDebounce', () => {
6+
beforeEach(() => {
7+
jest.useFakeTimers();
8+
});
9+
afterEach(() => {
10+
jest.useRealTimers();
11+
});
12+
test('debounce should work', () => {
13+
let count = 0;
14+
const updateCount = (step: number) => {
15+
count += step;
16+
};
17+
const hook = renderHook(() => useDebounce(updateCount, 300));
18+
19+
const debouncedFn = hook.result.current;
20+
21+
debouncedFn(1);
22+
debouncedFn(2);
23+
debouncedFn(3);
24+
expect(count).toBe(0);
25+
26+
jest.advanceTimersByTime(300);
27+
expect(count).toBe(3);
28+
29+
debouncedFn(1);
30+
debouncedFn.flush();
31+
expect(count).toBe(4);
32+
33+
debouncedFn(1);
34+
debouncedFn.cancel();
35+
jest.advanceTimersByTime(300);
36+
expect(count).toBe(4);
37+
38+
debouncedFn(1);
39+
hook.unmount();
40+
jest.advanceTimersByTime(300);
41+
expect(count).toBe(4);
42+
});
43+
});

src/useDebounce/demos/basic.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React, { useState } from 'react';
2+
import { Select } from 'antd';
3+
import { useDebounce } from 'dt-react-component';
4+
5+
export default () => {
6+
const [options, setOptions] = useState<{ label: string; value: string }[]>([]);
7+
8+
const debounceSearch = useDebounce(
9+
(input: string) => {
10+
const newOptions = input ? [{ label: input, value: input }] : [];
11+
setOptions(newOptions);
12+
},
13+
500,
14+
{
15+
maxWait: 1000,
16+
}
17+
);
18+
19+
return (
20+
<Select
21+
style={{ width: 430 }}
22+
showSearch
23+
placeholder="请输入进行搜索"
24+
options={options}
25+
onSearch={debounceSearch}
26+
/>
27+
);
28+
};

src/useDebounce/index.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
title: useDebounce 防抖函数
3+
group: Hooks
4+
toc: content
5+
---
6+
7+
# useDebounce
8+
9+
## 何时使用
10+
11+
用于接口请求防抖,函数防抖
12+
13+
## 示例
14+
15+
<code src="./demos/basic.tsx" title="基础使用"></code>
16+
17+
## API
18+
19+
`lodash.debounce``hooks` 形式,更多详见 [debounce](https://www.lodashjs.com/docs/lodash.debounce)
20+
21+
```ts
22+
const debouncedFn = useDebounce(
23+
func: (...args: any[]) => any,
24+
wait?: number,
25+
options?: Options
26+
);
27+
```
28+
29+
### Params
30+
31+
| 参数 | 说明 | 类型 | 默认值 |
32+
| ------- | -------------------- | ------------------------- | ------ |
33+
| func | 需要防抖执行的函数 | `(...args: any[]) => any` | - |
34+
| wait | 等待时间,单位为毫秒 | `number` | 500 |
35+
| options | 配置项 | `Options` | - |
36+
37+
## Options
38+
39+
| 参数 | 说明 | 类型 | 默认值 |
40+
| -------- | ------------------------ | --------- | ------- |
41+
| leading | 是否在延迟开始前调用函数 | `boolean` | `false` |
42+
| trailing | 是否在延迟开始后调用函数 | `boolean` | `true` |
43+
| maxWait | 最大等待时间,单位为毫秒 | `number` | - |

src/useDebounce/index.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { useCallback, useEffect, useRef } from 'react';
2+
import type { DebounceSettings } from 'lodash';
3+
import { debounce } from 'lodash';
4+
5+
const useDebounce = <T extends (...args: any) => any>(
6+
func: T,
7+
wait = 500,
8+
options?: DebounceSettings
9+
) => {
10+
const funcRef = useRef(func);
11+
funcRef.current = func;
12+
13+
const debouncedFunc = useCallback(
14+
debounce((...args) => funcRef.current(...args), wait, options),
15+
[]
16+
);
17+
18+
useEffect(() => () => debouncedFunc.cancel(), []);
19+
20+
return debouncedFunc;
21+
};
22+
23+
export default useDebounce;

0 commit comments

Comments
 (0)