Conditionally calling an API using React-Query hook

Tom Harvey picture Tom Harvey · Aug 13, 2020 · Viewed 11.3k times · Source

I am using react-query to make API calls, and in this problem case I want to only call the API if certain conditions are met.

I have an input box where users enter a search query. When the input value is changed, a search server is called with the contents of the input as the search query ... but only if the input value is more than 3 chars long.

In my react component I'm calling:

const {data, isLoading} = useQuery(['search', searchString], getSearchResults);

And my getSearchResults function will, conditionally, make an API call.

const getSearchResults = async (_, searchString) => {
    if (searchString.length < 3)
        return {data: []}

    const {data}  = await axios.get(`/search?q=${searchString}`)
    return data;
}

We can't use a hook inside a conditional - so I put the condition into my API calling function.

This almost works. If I enter a short query string, there is no API request made and I get an empty array back for the data. Yay!

But - isLoading will flip to true briefly - even though there is no HTTP request being made. So my loading indicator shows when there is no actual network activity.

Am I misunderstanding how to best solve my use case, is there a way to enure that isLoading will return false if there is no HTTP activity?

Answer

Tom Harvey picture Tom Harvey · Aug 13, 2020

The key was to use Dependent Queries

So, in my main component, I create a boolean and pass that to the enabled option of the useQuery hook:

const isLongEnough = searchString.length < 3;
const {data, isLoading} = useQuery(['search', searchString], getSearchResults, {enabled: isLongEnough});

and the API calling method is simply the API call - not any conditional:

const getSearchResults = async (_, searchString) => {
    const {data} = await axios.get(`/search?q=${searchString}`);
    return data;
}

The docs describe dependent queries as a solution for loading data from subsequent API endpoints, but the enable option can accept any boolean. In this case - if the search query string is long enough.