Caching the React Query Way!
Tags: webdev, javascript, beginners, programming
Published: 2022-11-19 18:44:57

Recently I had a chance to learn _react-query_, and after having used _Angular_ and _HttPClient_ for API calls for over an year I found this really amazing and easy to use as it provides bunch of different configurable parameters which solves a massive chunk of common problems for which we had to write functions manually.

A major problem that we all must have faced is CACHING! Traditionally, if we had to cache any data and prevent an API from being called again and again, we needed to store that data somewhere (in `BehaviourSubject` or `localstorage`, if you work with Angular) and every-time before calling an API we had to check if the data is already stored anywhere, if yes we could just use that or else go ahead and fetch data using API. A small code snippet for the same use case is provided


![Caching in Angular](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lxnw64p6vg4wmkz8pp4n.png)

The above is an example of `AppComponent` of angular where we are fetching the Super Heros data using `getSuperHeros` function. This function first checks if the data is already stored in a `BehaviourSubject`, and if it does it simply assigns the data to the `superHeros` variable else it goes ahead and makes an API call to fetch the data and store it in the `BehaviourSubject`.

Although there is no issue with the above implementation, one major question that arises is, "for how long the data will be cached?".

There are different answers for it based on what you use for storing the data.

If you've used `BehaviourSubject` or anything similar to it that persists till the page is reloaded, the data will be cached till page is reloaded.

If you've used `localstorage` that persists even if the page is reloaded, your data will be cached till the time you clear your localStorage. If you want your App to periodically look for changes, you'll have to store an interval along with the cached data and make API calls to see if the data from server has changed. 

Looks a very tedious job... right?

You can achieve the above functionality with just two properties in react-query.

1. cacheTime
2. staleTime

Before we dive into above properties a little bit about `useQuery` a very important hook from react-query


![Data Fetching using useQuery](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y81nurhf67y8vrmmzs38.png)


##useQuery

The above image is an basic example of how we fetch data in React using `useQuery` hook from react-query.

useQuery accepts multiple arguments first of which is `queryKey` an unique key (which in our case is very important), second is `queryFn` a function that is called to actually hit the endpoint, third is an object which contains multiple configurational options such as `refetchOnWindowFocus`, `cacheTime`, `staleTime`, etc...

It also returns an object which when expanded contains multiple fields of which `data`, `isLoading`, `isFetching`, being the important ones in context to this article

####- data

`data` is the same object that is returned from API, it is provided to us by useQuery

####- isLoading

`isLoading` is a boolean. It is set to `true` when the data fetched from the API is being loaded and set to `false` when the data is loaded completely

####- isFetching

`isFetching` is a boolean. It is set to `true` when the API call starts and set to `false` when the API call ends

Now let's have a look on the two properties that is used to achieve caching

##cacheTime

cacheTime property accepts time(in ms) which determines how long the data from the API will be cached. By default it is set to `5 mins`. 

In the above example, when we land on the App for the _first_ time the following steps takes place in order to show the data

1. useQuery hooks triggers `superHeroFetcher` function
2. `isFetching` is set to `true`
3. `isLoading` is set to `true`
4. API call takes place
5. `data` is populated
6. `isFetching` is set to `false`
7. `isLoading` is set to `false`

and then we're able to see the data fetched from API on screen.

But if we visit the App for the _second_ time the following steps takes place

1. useQuery hooks triggers `superHeroFetcher` function
2. `isFetching` is set to `true`
3. `isLoading` is set to `false`
4. API call takes place
5. `data` is populated
6. `isFetching` is set to `false`
7. `isLoading` is set to `false`

See the difference?

Since the data is cached, using the unique key (`queryKey`). `isLoading` property is never set to `true` and we won't see a Loading screen. However, an API call is still made and `isFetching` is set to `true` and then to `false` and if there is any change in data the updated data object is returned.

To prevent this extra API call, `staleTime` is the property that is to be used

##staleTime

staleTime property accepts time(in ms) too and it determines for how long the data that is cached will be stale. By default it is set to `0` which means everytime you visit a page the API call will be triggered. 


![cacheTime and staleTime in use](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80nn07signo9kpjjq70t.png)

In the above image both `staleTime` and `cacheTime` are set to 3 mins each.

Cheers!🥂