Reputation: 3948
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
Reputation: 15836
if someone is here because they are looking to disable cache, the cacheTime
has been renamed to gcTime
Upvotes: 4
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
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