The article is originally written here with images and code samples - https://easyontheweb.com/what-is-react-query-and-how-to-use-it/
In this article, we’ll be taking a look at an awesome library called React-query and see what react-query is, why we should use it in our React applications, and of course how we can use it in our applications.
Fetching data asynchronously and maintaining it in your React application is one of the most frustrating things to do, even though it isn’t difficult at first – things get complex real quick with fetching data and maintaining state of the fetched data.
I personally have used Redux as a cache store for fetched data before and it was really not a pleasant experience doing that. React-query in that sense is an absolute lifesaver, just like it’s sibling react-table.
Advantages of using react-query
I don’t like to blog a lot about particular libraries but react-query has quickly become one of my favourites of all time and therefore I would really like to stress on the advantages of react-query early on in the article to get you guys onboarded with me on the hype train.
Some of the advantages of react-query are :-
Automatic caching of data
Automatic refetching of fresh data on user actions
Super clean syntax
Using cached data
Loading, success and error state management by default
To be honest, this list would just go on and on and it’s not even in the scope of this article to discuss each of the points. That is also not the aim of the article, the aim is to make you aware of the benefits of and give you a glimpse of the powers that react-query gives to us.
For going in deeper and checking out everything that react-query provides you can always check out the documentation.
If you’ve ever found yourself writing code like this, or code similar to this inside a hook (yes, all you smarty pants), then react-query is the tool for you. Personally, I hate to use the loading and error states everywhere – even if you write custom hooks to do that, react-query just offers so much more.
This is the refactored code using useQuery from react-query. One thing you’ll notice directly is how react-query is returning isLoading, error and data . These were things we had to manage ourselves in the first version of the code.
All you need to do is import the useQuery hook from react-query and pass three arguments to it – a unique key for the query, a function that is the actual query and an optional config object we’ll discuss later.
Hence, react query decreases a whole lot of code. And when it comes to code, the lesser the surface area of the code, the lesser chances of bugs.
Now if you extract this to a hook as well, voila! You’ve DRY’ed out your code even further. But I’ll leave that to you guys..
One of the biggest advantages of react-query is it’s caching and synchronization mechanism. With options like initialData, staleTime, cacheTime etc. it is so easy and wonderful to work with, I can’t begin to explain.
Let’s think about what normally happens in a React application, you would store the data you want to cache in either Redux or whatever global state management mechanism you use and whenever you enter a component, you most probably have a useEffect where you fetch new data (or don’t, based on comparison with your cached data) and again store the newly fetched data into your global state.
This is hectic, buggy and does not give your a lot of options (unless you write those options yourself, again, increasing the surface area of the code).
With react-query, all this becomes a breeze. It uses the concept of something called stale data. If react-query sees that the data is stale, it tries to fetch newer data. By default the stale time is 0, ie, data becomes stale as soon as it is fetched.
The first option to consider is that of staleTime , longer the stale time, longer will react-query wait before considering the cached data as stale and try to fetch new data.
It is noteworthy that react-query does not implement polling in any sense, instead, it uses user activities to trigger the next synchronization of stale data.
Stale queries are refetched automatically in the background when:
New instances of the query mount
The window is refocused
The network is reconnected.
The query is optionally configured with a refetch interval.
All of these are configurable though using refetchOnMount, refetchOnWindowFocus, refetchOnReconnect and refetchInterval.
If you do not wish to keep on listening for user activities mentioned above, you can increase the staleTime for the query.
How is the caching of data done? Caching of data is based on the key + queryFunction combination that you use inside useQuery. Each unique combination is used to cache particular data.
Moreover, you will never have to see the ‘loading’ on your screen if a query has already been run once. Post that, the cached data will appear on screen initially and it will be updated once the synchronisation is complete. Slick, right?
To understand the complete caching lifecycle I highly recommend you to go through Caching Examples.
What do you think happens when we have this piece of code and we change the page number? Unfortunately, what happens is that the user sees the ‘loading’, i.e, the query goes into the loading state and then into the success state on every page change.
This happens because the key + queryFunction combination has changed with the change in the pageNumber. Therefore, react-query is not able to use the cached data. Well, even without react-query 99% of the apps work this way.
With react-query though, you have a great option called keepPreviousData. When this option is set to true in the configuration object, the data from the previous query is available even when the query changes and the data gets swapped with the new data as soon as the new data arrives. This is a better user experience as the user does not have to see the loading message again and again.
To read more about paginated queries check this out -> Paginated Queries.
useQuery is the hook we’ve been using so far, useQuery though is only used for GET queries. What about updation queries like PUT/DELETE/POST ? What does react-query have for us while working with these?
Just like the useQuery hook we react-query provides us with another cool hook called useMutation.
The official useMutation example from the docs
The syntax for useMutation is slightly complex when compared to that of useQuery. The useMutation hook itself accepts a function and a configuration object as arguments (note that there is no key here).
To call the mutation method though, you need to use the mutation.mutate method with the argument to be passed into the function used inside the useMutation.
All the states that were available to us in useQuery like error, isLoading, isSuccess etc are available for mutations as well.
Mutations also have callback methods that can be used in the configuration object for the useMutation hook. One of the most commonly used combinations is that of onSuccess and invalidateQueries.
react-query allows us to invalidate any or all queries and their cached data. Now, let us take a very common scenario – You add a new record in the database with the useMutation hook, in nearly 95% of the cases what you would like to do next is to fetch all the records again so that the new updated record gets displayed. To do this, we can use the invalidateQueries functionality.
When we invalidate any query, think of it as removing the cached data for that query and re-fetching the data for that query and storing the data in the global cache again.
Official example of useMutation with invalidateQueries
Note that in this example we are invalidating the data for two particular queries – todos and reminders and therefore react-query will automatically run the useQuery hook for these two and refetch and set the new data.
Semi Final words…
React-query is such a vast library with so many cool features that I cannot explain them all. As mentioned before, the goal of this article is not to act as documentation for react-query at all but to make developers aware of this awesome library that makes lives so much easier.
If you would like to learn more from the creator himself, do check this amazing video out on YouTube -> All about react-query
For more articles on ReactJS you can checkout the ReactJS section of the blog and it would be great if you join me and other web developers on this facebook group here – Easy on the web facebook group.