Caching with react-query and react-router-dom

Viewed 2417

I'm trying out react-query and want to see it caching. I have a page that gets a list of Books.

Note, some code obviously left out for brevity just trying to show the important parts.

const useBooks = options => {
  return useQuery(['books', options], bookApi.fetchBooks(options));
}

const Books = () => {
  useEffect(() => () => console.log("unmount"), []);
  const [options, setOptions] = useState({}); // options ex: { page: 1, search: "test"}
  const {error, isLoading, data} = useBooks(options);

  return books.map(book => <div>{book.name}</div>;
}

Now this Books is a "page" in my app using react-router-dom:

const App = () => {

  return (
    <Router>
      <>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/books">
          <Books />
         </Route>
      </>
     </Router>
    )
  }

When I go back and forth between "Home" and "Books" (by clicking Nav links in my app) I see the books fetch hitting the network every time. I also see "unmount" in the console.

I originally had the Routes wrapped in a Switch, and removed this but the Books component still appears to unmount. I am hoping it will not unmount and I will not see the network fetch, and the books will be pulled from the react-query cache. I also tried making the useBooks hook not use the search options param but the results were the same.

How do I use avoid the network fetch in my scenario?

1 Answers

react-router will unmount your component when you navigate away from it, yes. But that is on purpose and not the problem.

When a component that uses a react-query hook mounts, it will trigger a fetch (because of mounting). However, if you already have data in the cache for this specific key, you will instantly get that data returned as "stale data", and the fetch will happen in the background only.

If you want to avoid the request going out, you can either:

  • set refetchOnmount to false so that there will be no refetch when the component mounts
  • set a staleTime on your query

I would suggest setting the staleTime: It will tell react-query for how long the data should be considered "fresh". If you set it to 5 minutes, there will be no background-refetch for 5 minutes - the data will always come from the cache directly. staleTime defaults to 0, so you will always get background refetches.

Related