Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add useDebounce hooks #454

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ export { default as StatusTag } from './statusTag';
export { default as useWindowSwitchListener } from './switchWindow';
export { default as Table } from './table';
export { default as TinyTag } from './tinyTag';
export { default as useDebounce } from './useDebounce';
export { default as useIntersectionObserver } from './useIntersectionObserver';
export { default as useList } from './useList';
43 changes: 43 additions & 0 deletions src/useDebounce/__tests__/useDebounce.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { renderHook } from '@testing-library/react-hooks';

import useDebounce from '..';

describe('test useDebounce', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
test('debounce should work', () => {
let count = 0;
const updateCount = (step: number) => {
count += step;
};
const hook = renderHook(() => useDebounce(updateCount, 300));

const debouncedFn = hook.result.current;

debouncedFn(1);
debouncedFn(2);
debouncedFn(3);
expect(count).toBe(0);

jest.advanceTimersByTime(300);
expect(count).toBe(3);

debouncedFn(1);
debouncedFn.flush();
expect(count).toBe(4);

debouncedFn(1);
debouncedFn.cancel();
jest.advanceTimersByTime(300);
expect(count).toBe(4);

debouncedFn(1);
hook.unmount();
jest.advanceTimersByTime(300);
expect(count).toBe(4);
});
});
28 changes: 28 additions & 0 deletions src/useDebounce/demos/basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { useState } from 'react';
import { Select } from 'antd';
import { useDebounce } from 'dt-react-component';

export default () => {
const [options, setOptions] = useState<{ label: string; value: string }[]>([]);

const debounceSearch = useDebounce(
(input: string) => {
const newOptions = input ? [{ label: input, value: input }] : [];
setOptions(newOptions);
},
500,
{
maxWait: 1000,
}
);

return (
<Select
style={{ width: 430 }}
showSearch
placeholder="请输入进行搜索"
options={options}
onSearch={debounceSearch}
/>
);
};
43 changes: 43 additions & 0 deletions src/useDebounce/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: useDebounce 防抖函数
group: Hooks
toc: content
---

# useDebounce

## 何时使用

用于接口请求防抖,函数防抖

## 示例

<code src="./demos/basic.tsx" title="基础使用"></code>

## API

`lodash.debounce` 的 `hooks` 形式,更多详见 [debounce](https://www.lodashjs.com/docs/lodash.debounce)

```ts
const debouncedFn = useDebounce(
func: (...args: any[]) => any,
wait?: number,
options?: Options
);
```

### Params

| 参数 | 说明 | 类型 | 默认值 |
| ------- | -------------------- | ------------------------- | ------ |
| func | 需要防抖执行的函数 | `(...args: any[]) => any` | - |
| wait | 等待时间,单位为毫秒 | `number` | 500 |
| options | 配置项 | `Options` | - |

## Options

| 参数 | 说明 | 类型 | 默认值 |
| -------- | ------------------------ | --------- | ------- |
| leading | 是否在延迟开始前调用函数 | `boolean` | `false` |
| trailing | 是否在延迟开始后调用函数 | `boolean` | `true` |
| maxWait | 最大等待时间,单位为毫秒 | `number` | - |
17 changes: 17 additions & 0 deletions src/useDebounce/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useEffect, useRef } from 'react';
import type { DebounceSettings } from 'lodash';
import { debounce } from 'lodash';

const useDebounce = <T extends (...args: any) => any>(
func: T,
wait = 500,
options?: DebounceSettings
) => {
const debouncedFuncRef = useRef(debounce(func, wait, options));
const debounceFnnc = debouncedFuncRef.current;
JackWang032 marked this conversation as resolved.
Show resolved Hide resolved
useEffect(() => () => debounceFnnc.cancel(), []);

return debounceFnnc;
};

export default useDebounce;
Loading