Skip to content

Commit d7b9210

Browse files
committed
Added Debounced API Query Component (#373)
1 parent 46953f9 commit d7b9210

1 file changed

Lines changed: 44 additions & 0 deletions

File tree

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React, { useState, useRef, useEffect } from 'react';
2+
3+
export default function DebouncedQueryHandler({ queryFn, delay = 500, children }) {
4+
const [data, setData] = useState(null);
5+
const [loading, setLoading] = useState(false);
6+
const [error, setError] = useState(null);
7+
const timeoutRef = useRef(null);
8+
const abortControllerRef = useRef(null);
9+
10+
const runQuery = (input) => {
11+
// Cancel previous debounce
12+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
13+
14+
timeoutRef.current = setTimeout(async () => {
15+
// Cancel previous request
16+
if (abortControllerRef.current) abortControllerRef.current.abort();
17+
abortControllerRef.current = new AbortController();
18+
19+
setLoading(true);
20+
setError(null);
21+
22+
try {
23+
const result = await queryFn(input, { signal: abortControllerRef.current.signal });
24+
setData(result);
25+
} catch (err) {
26+
if (err.name !== 'AbortError') {
27+
setError(err);
28+
}
29+
} finally {
30+
setLoading(false);
31+
}
32+
}, delay);
33+
};
34+
35+
// Cleanup on unmount
36+
useEffect(() => {
37+
return () => {
38+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
39+
if (abortControllerRef.current) abortControllerRef.current.abort();
40+
};
41+
}, []);
42+
43+
return children({ runQuery, data, loading, error });
44+
}

0 commit comments

Comments
 (0)