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?
React Query is a library that has 2 simple hooks which provide fetching, caching and updating asynchronous data in React applications. It was created by open sourcerer Tanner Linsley in 2019, and now it is proven that it is very useful in server state management in React applications.
react-query stores the cache in-memory. If you want to additionally sync the storage somewhere else, have a look at the persistQueryClient plugin.
React-Query — The good partsIt provides valuable tools to improve reliability of server data (invalidating data and marking data as stale). It provides Tools to improve fetch UX (prefetching, re-fetching, caching, and more).
The QueryCache is the storage mechanism for React Query. It stores all the data, meta information and state of queries it contains. Normally, you will not interact with the QueryCache directly and instead use the QueryClient for a specific cache.
From Importaint 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
});
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>
);
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With