Reputation: 253
I was following an example I saw on YouTube for using React Query, but I can't seem to get the caching to work as expected. In my app the data is fetched every time. Not sure if I'm missing something obvious. Here is my code: https://codesandbox.io/s/eager-faraday-nhmlb?file=/src/App.js
When clicking the Planets and People buttons, I can see network requests being made each time I flip back and forth. I would expect to see it make a request for each set of data once at least for some time while the cache is still active.
Anyone know what might be wrong?
Upvotes: 23
Views: 26193
Reputation: 9
"use client";
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
export default function QueryClientProviderInit({ children }) {
const [queryClient] = React.useState(() => new QueryClient());
return (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);
}
You can try this way to only return queryClient
once in whole life cycle
Upvotes: 0
Reputation: 11
the issue is all about creating new instances with new QueryClient, create a file and name it queryClient.ts, and put this into that:
import { QueryClient } from "@tanstack/react-query";
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
retry: 1,
staleTime: 1000 * 60 * 5,
gcTime: 1000 * 60 * 5,
},
},
});
since now use this exported queryClient instead of creating one and throwing away the previous cashes.
Upvotes: 0
Reputation: 81773
From Important Defaults section:
Query instances via
useQuery
oruseInfiniteQuery
by default consider cached data as stale.
Stale queries are refetched automatically in the background when:
- New instances of the query mount
By default, when a query is successfully fetched, it's considered stale immediately, that's why your data is refetched every time you change the tab. You can set a longer staleTime
(default to 0
) if you don't want the aggressive refetching behavior:
const { isLoading, error, data } = useQuery("planets", fetchPlanets, {
staleTime: 10000, // only eligible to refetch after 10 seconds
});
Optionally, you can set staleTime
globally for all queries during QueryClient instantiation, like so:
const queryClient = new QueryClient({
defaultOptions: { queries: { staleTime: 10000 }}
});
There is another error in your code not very related to react-query
, in this code of yours below:
function App() {
const [page, setPage] = useState("planets");
const queryClient = new QueryClient();
const pageSetter = (page) => {
setPage(page);
};
return (
<QueryClientProvider client={queryClient}>
<div className="App">
<h1>Star Wars Info</h1>
<Navbar setPage={pageSetter} />
<div className="content">
{page === "planets" ? <Planets /> : <People />}
</div>
</div>
</QueryClientProvider>
);
}
Every time the user clicks the buttons to display different data, the whole component gets re-render, a new instance of queryClient
is created and passed to QueryClientProvider
, resetting any internal state of the client cache. You should decouple your component to avoid unnecessary re-render like this:
function Content() {
const [page, setPage] = useState("planets");
const pageSetter = (page) => {
setPage(page);
};
return (
<div className="App">
<h1>Star Wars Info</h1>
<Navbar setPage={pageSetter} />
<div className="content">
{page === "planets" ? <Planets /> : <People />}
</div>
</div>
);
}
// top level component, should not get re-rendered
function App() {
const queryClient = new QueryClient();
return (
<QueryClientProvider client={queryClient}>
<Content />
</QueryClientProvider>
);
}
Upvotes: 40
Reputation: 29056
You are creating a new QueryClient inside the app component, so when it re-renders, you basically throw away the cache. Create the new QueryClient ()
outside of the app like in the example.
Also, please note that you will then still see network requests, because react-query will do background refetches with the default staleTime of 0 when a component mounts. You can set it to something higher if you don’t want that.
Upvotes: 19