wy125
wy125

Reputation: 253

React Query doesn't seem to be caching

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

Answers (4)

Tú Trần
Tú Trần

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

shahin behzadrad
shahin behzadrad

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

NearHuscarl
NearHuscarl

Reputation: 81773

From Important Defaults section:

Query instances via useQuery or useInfiniteQuery 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>
  );
}

Live Demo

Edit 67040687/react-query-doesnt-seem-to-be-caching

Upvotes: 40

TkDodo
TkDodo

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

Related Questions