Fetch a query only once until page refresh using React Query

David Han
In the weeds
Published in
3 min readApr 1, 2021

--

At Greenhouse, we’re currently working on a reports dashboard. Typically, based on how many widgets you have on your dashboard, there are a number of queries that need to run, and based on the amount of data you have, these queries may take a while to complete. Given this performance problem, we decided that we wanted to have our queries run only once and that anytime you come back to the dashboard page, we’ll read from the cache instead of re-fetching the data. Note that this primarily works in a single-page app context since the data is only cached on the front end. We’ll still run the query when a user refreshes the browser but until then we’ll access the data from the cache.

React Query makes this easy to do. Here is a quick example:

import React from "react";
import { QueryClient, QueryClientProvider } from "react-query";
import { useQuery } from "react-query";
import axios from "axios";

const twentyFourHoursInMs = 1000 * 60 * 60 * 24;
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
refetchOnmount: false,
refetchOnReconnect: false,
retry: false,
staleTime: twentyFourHoursInMs,
},
},
});

function AppContent() {
const filters = [{ date_range: 'lastNinetyDays' }];
const { data } = useQuery(
["uniqueKey", filters], () =>
axios
.get("path/to/data", { params: filters })
.then((response) => response.data)
);

return <div>{data && data.value}</div>;
}

export default function App() {
return (
<QueryClientProvider client={queryClient}>
<AppContent />
</QueryClientProvider>
);
}

Turning off library defaults

const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
refetchOnmount: false,
refetchOnReconnect: false,
retry: false,
staleTime: twentyFourHoursInMs,
},
},
});

By default, React Query will immediately consider a query to be stale as soon as it is fetched. Based on their docs stale queries are re-fetched automatically in the background when:

  • New instances of the query mount
  • The window is refocused
  • The network is reconnected.

We turned off most of the library defaults because it’s okay for the data we’re displaying to be stale for some time. We chose a time of 24 hours before the data is considered stale so that users who keep their browser tabs open without refreshing the page will at least get their data updated every 24 hours.

Query Key

The first parameter of the useQuery function is a query key. After the query is fetched for the first time, this query key is used to determine whether the query is the same, in which case the library will read from the cache instead of running a new query. The query key can be a string or an array. In our case, we’re using an array that includes the dashboard filters. This allows us to run a new query whenever a user changes a dashboard filter but anytime they use a filter that they previously used, the cached data is displayed instead.

React Query is a powerful library that has all sorts of features like, mutations, optimistic updates, infinite scroll support, and more. This post covers the bare minimum you need to know to support a basic query caching use case. I hope this was helpful!

We’re hiring!

--

--