Skip to content

Commit 027711b

Browse files
fix(useThrottle): fix useThrottle with both leading and trailing (#213)
1 parent fc97ca5 commit 027711b

2 files changed

Lines changed: 88 additions & 1 deletion

File tree

src/hooks/useThrottle/throttle.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export function throttle<F extends (...args: any[]) => void>(
3535
if (Date.now() - pendingAt >= throttleMs) {
3636
pendingAt = Date.now();
3737
debounced.cancel();
38-
debounced(...args);
3938
}
4039
}
4140

src/hooks/useThrottle/useThrottle.spec.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,92 @@ describe('useThrottle', () => {
2626

2727
vi.restoreAllMocks();
2828
});
29+
30+
it('should throttle function calls', async () => {
31+
const callback = vi.fn();
32+
const { result } = await renderHookSSR(() => useThrottle(callback, 100));
33+
34+
result.current();
35+
result.current();
36+
result.current();
37+
38+
expect(callback).toHaveBeenCalledTimes(1);
39+
});
40+
41+
it('should trigger a trailing call after wait time', async () => {
42+
vi.useFakeTimers();
43+
44+
const callback = vi.fn();
45+
const throttleMs = 50;
46+
const { result } = await renderHookSSR(() => useThrottle(callback, throttleMs));
47+
48+
result.current();
49+
result.current();
50+
expect(callback).toBeCalledTimes(1);
51+
52+
await vi.advanceTimersByTimeAsync(throttleMs + 1);
53+
expect(callback).toBeCalledTimes(2);
54+
55+
vi.useRealTimers();
56+
});
57+
58+
it('should call the function with correct arguments', async () => {
59+
const callback = vi.fn();
60+
const throttleMs = 50;
61+
const { result } = await renderHookSSR(() => useThrottle(callback, throttleMs));
62+
63+
result.current('test', 123);
64+
65+
expect(callback).toHaveBeenCalledTimes(1);
66+
expect(callback).toHaveBeenCalledWith('test', 123);
67+
});
68+
69+
it('should execute immediately if not called within wait time', async () => {
70+
vi.useFakeTimers();
71+
72+
const callback = vi.fn();
73+
const throttleMs = 500;
74+
const { result } = await renderHookSSR(() => useThrottle(callback, throttleMs));
75+
76+
result.current(); // should execute
77+
expect(callback).toHaveBeenCalledTimes(1);
78+
79+
await vi.advanceTimersByTimeAsync(throttleMs + 1);
80+
81+
result.current(); // should execute again
82+
expect(callback).toHaveBeenCalledTimes(2);
83+
84+
vi.useRealTimers();
85+
});
86+
87+
it('should execute on leading and trailing when called multiple times with leading and trailing', async () => {
88+
vi.useFakeTimers();
89+
90+
const callback = vi.fn();
91+
const throttleMs = 50;
92+
const { result } = await renderHookSSR(() => useThrottle(callback, throttleMs, { edges: ['leading', 'trailing'] }));
93+
94+
result.current();
95+
96+
await vi.advanceTimersByTimeAsync(throttleMs + 1);
97+
98+
expect(callback).toHaveBeenCalledTimes(1);
99+
100+
result.current();
101+
102+
await vi.advanceTimersByTimeAsync(throttleMs);
103+
104+
expect(callback).toHaveBeenCalledTimes(2);
105+
106+
result.current();
107+
result.current();
108+
109+
expect(callback).toHaveBeenCalledTimes(3);
110+
111+
await vi.advanceTimersByTimeAsync(throttleMs);
112+
113+
expect(callback).toHaveBeenCalledTimes(4);
114+
115+
vi.useRealTimers();
116+
});
29117
});

0 commit comments

Comments
 (0)