Search code examples
reactjsaxioslodashreact-query

How to use debounce with useQuery in React Query?


I am using React Query to fetch data from an API in a React app. I want to implement debounce for better performance, but I'm having trouble getting it to work with useQuery. When I try to wrap my API call in a debounced function, I get an error saying "query function must return a defined value".

Here is the code I am currently using:

    async function fetchProducts() {
        const response = await axios.get(`/api/products?category_id=${category_id}&${searchParams.toString()}&page=${page}`);
        return response.data;
    }

    const debouncedFetchProducts = React.useMemo(
        () => _.debounce(fetchProducts, 500),
        [fetchProducts]
    );

    // The following queries will execute in parallel
    const categoryQuery = useQuery({ queryKey: ['category'], queryFn: fetchCategory, keepPreviousData: true });
    const productsQuery = useQuery({ queryKey: ['products', category_id, sortPrice, minPrice, maxPrice, page, categoryFilters], queryFn: debouncedFetchProducts, keepPreviousData: true, staleTime: 1000 });

When I run this, I get an error saying "query function must return a defined value". I believe this is because the debounced function returns a promise, but useQuery expects an actual value.

I have also tried using useAsync, but I would like to use useQuery because it has built-in caching.

Can someone help me figure out how to implement debounce with useQuery in React Query?

Thank you in advance for your help!


Solution

  • You can utilize the useDebounce hook to trigger a queryKey update in react-query instead of using the debounce function from the Underscore library.

    For example:

    const [searchParams, setSearchParams] = useDebounce([category_id, sortPrice, minPrice, maxPrice, page, categoryFilters], 1000)
    const productsQuery = useQuery({ queryKey: ['products', ...searchParams], queryFn: fetchProducts, keepPreviousData: true, staleTime: 1000 });
    
    

    useDebounce is applied to the searchParams array, which includes variables like category_id, sortPrice, minPrice, maxPrice, page, and categoryFilters.

    The debounce delay is set to 1000 milliseconds (1 second). The productsQuery then uses the debounced search parameters in its query key, ensuring that the fetchProducts function is only called when the debounced search parameters change.

    You can find a working useDebounce example in this codesandbox example