mirror of
https://github.com/streamich/react-use.git
synced 2025-12-08 18:02:14 +00:00
useDebounce:
- tests; - fix function change debounce clear and reset; - declare return type;
This commit is contained in:
parent
00e0c2691b
commit
42fdec140b
@ -48,12 +48,12 @@ const Demo = () => {
|
||||
const [
|
||||
isReady: () => boolean | null,
|
||||
cancel: () => void,
|
||||
] = useDebounce(fn: Function, ms: number, args: DependencyList = []);
|
||||
] = useDebounce(fn: Function, ms: number, deps: DependencyList = []);
|
||||
```
|
||||
|
||||
- **`fn`**_`: Function`_ - function that will be called;
|
||||
- **`ms`**_`: number`_ - delay in milliseconds;
|
||||
- **`args`**_`: DependencyList`_ - array of values that the debounce depends on, in the same manner as useEffect;
|
||||
- **`deps`**_`: DependencyList`_ - array of values that the debounce depends on, in the same manner as useEffect;
|
||||
- **`isReady`**_`: ()=>boolean|null`_ - function returning current debounce state:
|
||||
- `false` - pending
|
||||
- `true` - called
|
||||
|
||||
116
src/__tests__/useDebounce.test.ts
Normal file
116
src/__tests__/useDebounce.test.ts
Normal file
@ -0,0 +1,116 @@
|
||||
import { act, renderHook, RenderHookResult } from '@testing-library/react-hooks';
|
||||
import { DependencyList } from 'react';
|
||||
import { useDebounce } from '../index';
|
||||
import { UseDebounceReturn } from '../useDebounce';
|
||||
|
||||
describe('useDebounce', () => {
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllTimers();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(useDebounce).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return three functions', () => {
|
||||
const hook = renderHook(() => useDebounce(() => {}, 5));
|
||||
|
||||
expect(hook.result.current.length).toBe(2);
|
||||
expect(typeof hook.result.current[0]).toBe('function');
|
||||
expect(typeof hook.result.current[1]).toBe('function');
|
||||
});
|
||||
|
||||
function getHook(
|
||||
ms: number = 5,
|
||||
dep: DependencyList = []
|
||||
): [jest.Mock, RenderHookResult<{ delay: number; deps: DependencyList }, UseDebounceReturn>] {
|
||||
const spy = jest.fn();
|
||||
return [
|
||||
spy,
|
||||
renderHook(({ delay = 5, deps = [] }) => useDebounce(spy, delay, deps), {
|
||||
initialProps: {
|
||||
delay: ms,
|
||||
deps: dep,
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
it('should call passed function after given amount of time', () => {
|
||||
const [spy] = getHook();
|
||||
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
jest.advanceTimersByTime(5);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should cancel function call on unmount', () => {
|
||||
const [spy, hook] = getHook();
|
||||
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
hook.unmount();
|
||||
jest.advanceTimersByTime(5);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('first function should return actual state of debounce', () => {
|
||||
let [, hook] = getHook();
|
||||
let [isReady] = hook.result.current;
|
||||
|
||||
expect(isReady()).toBe(false);
|
||||
hook.unmount();
|
||||
expect(isReady()).toBe(null);
|
||||
|
||||
[, hook] = getHook();
|
||||
[isReady] = hook.result.current;
|
||||
jest.advanceTimersByTime(5);
|
||||
expect(isReady()).toBe(true);
|
||||
});
|
||||
|
||||
it('second function should cancel debounce', () => {
|
||||
const [spy, hook] = getHook();
|
||||
const [isReady, cancel] = hook.result.current;
|
||||
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(isReady()).toBe(false);
|
||||
|
||||
act(() => {
|
||||
cancel();
|
||||
});
|
||||
jest.advanceTimersByTime(5);
|
||||
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(isReady()).toBe(null);
|
||||
});
|
||||
|
||||
it('should reset timeout on delay change', () => {
|
||||
const [spy, hook] = getHook(50);
|
||||
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
hook.rerender({ delay: 5, deps: [] });
|
||||
|
||||
jest.advanceTimersByTime(5);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should reset timeout on deps change', () => {
|
||||
const [spy, hook] = getHook(50, [5, 6]);
|
||||
|
||||
jest.advanceTimersByTime(45);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
hook.rerender({ delay: 50, deps: [6, 6] });
|
||||
|
||||
jest.advanceTimersByTime(45);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
jest.advanceTimersByTime(5);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@ -1,9 +1,16 @@
|
||||
import { DependencyList, useCallback } from 'react';
|
||||
import { DependencyList, useEffect } from 'react';
|
||||
import useTimeoutFn from './useTimeoutFn';
|
||||
|
||||
export default function useDebounce(fn: (...args: any[]) => any, ms: number = 0, args: DependencyList = []) {
|
||||
const cb = useCallback(fn, args);
|
||||
const [isReady, cancel] = useTimeoutFn(cb, ms);
|
||||
export type UseDebounceReturn = [() => boolean | null, () => void];
|
||||
|
||||
export default function useDebounce(
|
||||
fn: (...args: any[]) => any,
|
||||
ms: number = 0,
|
||||
deps: DependencyList = []
|
||||
): UseDebounceReturn {
|
||||
const [isReady, cancel, reset] = useTimeoutFn(fn, ms);
|
||||
|
||||
useEffect(reset, deps);
|
||||
|
||||
return [isReady, cancel];
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user