13 April 2021
React Query tutorial for server-state data management
Restore your faith in server-state data synchronization with the pre-configured React Query library. See how you can bring fetch, cache, and update logic to a few understandable lines of code with simple automation hooks presented in this tutorial.
Why is it the next big thing?
It was React’s missing piece that helps with server-state data management. Forget about keeping everything in a standard global state, because most libraries were created to handle client state only and the server state is way different.
Server data is asynchronous. As it’s not stored in your app, it can go out of date in a blink, so you should figure out a way for building cache. Here’s the bad news — it’s one of the hardest things in programming. But the good news is that React Query can handle your data fetching, caching, synchronizing, and updating the server state.
Why is it cool to start a fetching data project with React Query?
One-liner time — it will take your app to a new level. But really, consider the examples below.
Key benefits of React Query
- Window focus refetching – when a user leaves your app tab, React Query marks the data “stale” and refetches it when that person returns.
- Request retry – you can set an amount of retries for any request to combat random errors.
- Prefetching – if your React Query function app needs fresh data after an update request, you can prefetch the query with a specific key, and React Query will update it in the background.
- Optimistic Updates – when you edit or delete an item in a list, you can issue an optimistic update of the list.
Starting the React Query engine
Here’s the basic configuration.
Let’s assume we have a basic axios
function which returns data for our articles.
Data fetching with the help of React Query is really simple.
Data fetching is now better
Why is it better than common fetch data with the useEffect
pattern? When you use that query with the same projects
key, React Query first returns previously fetched data, and then it fetches it again.
When the second data set is the same as the first set, React Query keeps both as a reference without forcing a reload. That’s a tremendous improvement to UX work.
How update hooks work
So you know how to fetch data easier. Let’s see how to update it.
React Query has the useMutation
hook you can use to update/create/delete data. useMutation
gives you access to the mutate function to which we can pass necessary arguments. it then returns information about the status of our API call. The status can be:
idle
for an idle or fresh/reset stateloading
for a mutation that is currently running
error
when we encountered onesuccess
when everything was ok and our data is available
💡 I heard you like hooks
You can access the status information from the status variable or, for those who prefer boolean states , they’re accessible through the following variables.
isIdle
isLoading
isError
isSuccess
As you see, it’s super easy to use. As there are more options you can pass to useMutation
, React Query can become one of your most powerful developer tools.
Need proven React developers to crush that backlog?
🙌🏼 Access talent building in React.js, React Native, TypeScript, or Next.js. Trusted by 98% of CTOs, according to Clutch.
Discover what your project needs from our seniors on a free, 1-hour call that’s 100% non-binding.
Here is the real power
What happens when a device goes offline for a moment while sending data? React Query has a solution for that!
Use Request Retry
You can pass the retry
option with the number of times the Query should retry the mutation after reconnection.
Query Client helps a lot with caching
The function packs in a lot of methods you can use to handle cache.
invalidateQueries
method marks a query with a given key as invalid to make React Query fetch that data again. You can use that method in useMutation hook after a successful update (example below).setQueryData
, used for optimistic updates of the query’s cached data.prefetchQuery
method can help you to prefetch some data before it’s needed and rendered with useQuery. If you know when the user needs that particular data, use that method to fetch it earlier to improve UX.clear
simply clears all connected caches.
To use these methods, import the useQueryClient
hook from the React Query library. Then, assign it to the const queryClient = useQueryClient()
variable, and call your method on that variable with queryClient.invalidateQueries()
.
useMutation hook options
In most cases, you will use the Query Client methods inside of hooks options. Let’s look at the latter now.
onMutate
function fires beforeuseMutation
. It’s quite helpful when you want to run optimistic updates on local cache and update data for the UI before the mutation happens on the server.onSuccess
function’s code runs when the mutation is successful. Queries with key articles get refetched in the background. Let’s see that in an example below.
onError
fires when the mutation encounters an error, and it takes the context as one of arguments. It’s very common to set cache to previous data when something goes awry.
useQuery hook and other hot functionalities
Parallel queries
React query’s useQueries
hook lets you execute many queries simultaneously to maximize fetching concurrency. It accepts an array of queries options objects — like the useQuery
hook — to return an array of query results.
Dependent queries
They’re useful when you want to use data returned from one query to execute another one. Do that with the enabled
option in useQuery
.
Paginated queries
This is a very common concept that every developer uses daily. Just nod your head, please. And finally, React Query can help you use them better!
You just need to pass the page number to the queryKey
array and use the keepPreviousData
option in the useQuery
hook. Afterward, when you jump between pages, you get cache data from the first one with new data loading in the background. The UI won’t reload when the data is the same as before.
Optimistic updates
So what’s that optimistic update? Is it positive :)? Let’s say you have a simple star rating system in an article.
With optimistic updates implemented, when you give the article a star, the UI accepts the command immediately without waiting for a server response. The code ensures the system will run an optimistic update before performing a mutation. Here is an example from React Query’s documentation.
💡 Grab our open-source React toolkit packed with goodies you need
Data handling done smarter
React Query hooks really help us nail the problems with asynchronous data handling. With the React query hook, life used to be harder, in particular server state management. Developers needed a bunch of other libraries, and they’d end up putting the server data into a global store. Not a great idea. Why? As I mentioned earlier, keeping asynchronous server data in a global store adds unnecessary complexity to our code.
There’s more. The Query also helps to reduce the amount of boilerplate code (such as keeping every fetch in useEffect hook). It has positive influence on aspects such as error handling, data object or API endpoint optimization etc. Use React Query well and it will help revamp the user experience BUT it can also break it. So be careful and try to get to know this library first.