Gambit2007
Gambit2007

Reputation: 3948

React Query - query is not using cache?

I have the following definition of useQuery that i use in a couple of React components:

useQuery("myStuff", getMyStuffQuery().queryFn);

Where getMyStuffQuery looks like this:

export const getMyStuffQuery = () => {
    return {
    queryFn: () => makeSomeApiCall(),
}}

I would expect that although all of those components render, makeSomeApiCall() would only make an API call once, and the rest of the time will use the cache resulted in from this first call.

However, it seems like it keeps calling makeSomeApiCall() again and again, whenever any of said components renders.

Why is React Query not using the cache? Am i doing something wrong?

Upvotes: 19

Views: 43259

Answers (3)

ProllyGeek
ProllyGeek

Reputation: 15836

if someone is here because they are looking to disable cache, the cacheTime has been renamed to gcTime

Upvotes: 4

3DPrintScanner
3DPrintScanner

Reputation: 1014

React Query has a slightly different model of request caching.

A request can have its results cached, and those results can go stale.

Cached results are returned immediately, but if stale they are re-fetched in the background and the cache is updated.

The default configuration caches results for 5 minutes and makes them stale immediately.

See: https://tanstack.com/query/v4/docs/guides/caching

The cacheTime and staleTime can be set as part of the useQuery options object as shown here for a 5 minute cache time and 1 minute stale time.

useQuery({ queryKey: ['todos'], queryFn: fetchTodos, staleTime: 1 * 60 * 1000, cacheTime: 5 * 60 * 1000 });

The refetching cached results strategy can be changed with options like refetchOnWindowFocus

See: https://tanstack.com/query/v4/docs/guides/important-defaults

You can stop this refetching of stale values on the window focus event like this:

const client = new QueryClient({
  defaultOptions: {
    queries: {
      refetchOnWindowFocus: false,
    },
  },
});

Upvotes: 11

Andy Noelker
Andy Noelker

Reputation: 11269

React Query will cache the data of the query by default, but that does not affect whether or not it thinks that data is stale. If it thinks data is stale, it will call the query function (hit the API) every time useQuery() is called. This means it will read the data from the cache if it has it, but since it thinks that data is stale, will still hit the API in the background to fetch any updated data.

Fortunately, you have complete control over whether or not React Query considers data to be stale. You can set a staleTime config option to control how long specific data should be considered fresh. You can even set it to Infinity to say that as long as your app is open, it should only ever call the query function (hit the API) one time. By default this value is 0, which is why you are seeing the behavior you are - React Query will refetch the data in the background every time useQuery is called because it immediately thinks that data is stale (even though it's still cached).

In your example, if you truly ever only wanted an API to be called one time, you could simply set the staleTime option to Infinity.

useQuery("myStuff", getMyStuffQuery().queryFn, { staleTime: Infinity });

This option, along with all others, can be read about in the docs here https://react-query.tanstack.com/reference/useQuery

Upvotes: 35

Related Questions