Data fetching and caching quickly becomes cumbersome and complex without the right tools
More often than not, our React applications serve the purpose of rendering data sets. Creating components and styling them is one part of the story. But our data needs to come from somewhere. In many cases, we fetch data from an API — whether our own API or a third-party one.
There are many aspects to this data fetching: caching the data, error handling, authenticating requests, and refetching stale data, to name a few.
In the last years, many solutions appeared to help us with the mentioned tasks:
Let’s briefly review these seven popular tools, with some boilerplate code showing how each solution is implemented in practice.
You can find working examples in my GitLab repository (each example is a different branch).
Note: we review them in order of complexity. We start with some more complex and complete tools, and end with the more simple ones. Also note that we completely ignore error handling in the code examples, so we can focus on core functionality.
Relay (or “Relay Modern,” as the second version was called) is an advanced framework for building data-driven applications with React and GraphQL, created by Facebook.
After initial trials and experiments, Relay Modern was released on April 18, 2017, after it had been developed and rehauled by Greg Hurell and Joe Savona, among several others. Greg wrote a nice backstory about the development on his blog.
This is not a tool for the faint-hearted. It requires quite a bit of boilerplate code and setup before you can start. And even after that’s all in place, you will be left with many questions and challenges if you have little knowledge about it.
To get started, you need to define a generic fetch function, a so-called Relay Environment, and you need to have the Relay Compiler running (preferably as a watch process during development). The GraphQL schema also needs to be stored in your repository (
get-graphql-schema might come in handy for you).
To a small extent, it’s comparable with Relay (but be aware, there are also major differences).
It’s a library that I’ve been using a lot myself. The key takeaway for me with this library is that it’s doing its job well and is highly customizable, but you have to be careful with caching strategies. By default, caching seems to work fine — and to be honest, it does. But as soon as your application starts to grow and you need functionality such as pagination or data filtering (e.g., running the same query several times with different variables), you might run into a scenario where you have to customize the caching functionality. And it quickly becomes quite a challenge to maintain this logic.
Compared to Relay, it’s easier to set up and get going. You define a client, make the client available with a dedicated provider, and you’re pretty much good to go. But don’t underestimate the effort you must put into customizing your setup before you’re satisfied.
Note: TanStack Query used to be called
react-query. They rebranded to TanStack Query in July 2022 (source) and they will soon have adapters for several frameworks, such as Vue, Svelte, and Solid. At the time of writing the only adapter that’s finished is an implementation for React, conveniently called
Before we move on to less sophisticated libraries and tools, we can look at another big player in the game: TanStack Query. Used by companies such as Microsoft, Volvo, eBay, and Uber, we would be foolish to skip this one.
It works out of the box, but it’s highly configurable and has a lot of functionality, such as support for refetching on window focus, pagination, prefetching, scroll restoration, and much more.
It requires a small amount of boilerplate code to get going. Again, like we just saw with Apollo Client, we need to create a client, make it available with a provider, and we can start using the available hooks:
Not as popular as Apollo Client and TanStack Query, but definitely not a package to ignore: Vercel’s SWR (Vercel is the creator of Next.js).
Compared with the other three solutions we already looked at, SWR is by far the easiest to start using. You simply import and use the
useSWR hook to fetch your data with a custom, user-defined fetch function (we’re using the native Fetch API in this example):
Don’t be fooled by the simpleness of all this. The hooks provided by SWR are packed with power, and support, for example, pagination, mutations, prefetching, and SSR (Server Side Rendering).
React-async-hook is a tiny library created by Sébastien Lorber (author of the newsletter
thisweekinreact.com), and it’s not seeing as much usage as the more full-featured libraries we’ve already looked at. That being said, comparing them is not fair (the primary argument is that react-async-hook does not have built-in support for caching — by design).
The first line of the readme file reads:
“This tiny library only does one thing, and does it well.”
And although the readme file lists several features, all it boils down to is: This library is very good at fetching data (using the provided
You can cancel the requests, trigger refetching, and handle mutations and race conditions, to name some of the supported features. As you can see, it all depends on making requests to fetch data. The author also considers the library feature-complete, which means there is no active development (the latest commit that changed the actual code was in September 2021).
But given the small commits to the readme file now and then, Sébastien seems to keep an eye on it.
Similar to SWR, it’s easy to use react-async-hook. Here’s the code:
With more than 30 million downloads per week (!), we can safely conclude that Axios is a powerful little tool that does its job very well. Many popular libraries have Axios as a dependency.
“Axios is a simple promise-based HTTP client for the browser and node.js.”
In other words, we can use it to (highly) configure and make HTTP requests. It works very well with the more full-featured libraries we looked at above, which require us to provide our own fetch functionality (such as TanStack Query and SWR). This is definitely the case if you need to have fine-grained control over your HTTP requests.
If you’ve been around for a while, you might remember when it was common to use jQuery’s
$.ajax() function to make asynchronous “Ajax” requests. In one way, we can compare Axios with jQuery’s
ajax() function (but I don’t think I’m doing Axios justice with that statement ).
Note that Axios is very raw and bare-boned. It’s not a full-blown solution for data fetching in your React application. But it can supplement libraries like TanStack Query and SWR, so you’ll have a full solution for your data flow.
Suppose you’re new to React and don’t have much experience with data fetching. In that case, I recommend playing around with Axios for a little while (or the Fetch API, see next chapter) to better understand what’s going on before you move on to more complex functionality.
A very minimalistic example of fetching data with Axios:
Last but not least, we should mention the Fetch API, which is natively supported by pretty much all major browsers. And with the release of Node.js 18 in April 2022, a global
fetch function is enabled by default (although they called it an experimental feature in the announcement) for usage in Node.js-driven backend environments.
The Fetch API is the modern answer for making HTTP requests. But remember that it’s quite a low-level API. You can make requests with it, but that’s it. It’s not a complete solution for your applications (note the similarity with Axios in that regard).
So, the Fetch API and Axios are similar in many ways. Note that if your application requires backward compatibility with older browsers, it’s recommended to use Axios instead (or alternatively, a polyfill for the Fetch API).
Fetching data from a server and having a local data (state) and caching strategy is essential for most applications. Luckily several solutions have been developed over the years that save us a lot of headaches.
I wrote a small text about seven popular tools and libraries that you should know of. But if you want to become a good (React) developer, you should first aim to get a good understanding of what’s going on “behind the scenes” regarding data fetching and caching.
Remember, you can find all working examples in my GitLab repository (each example is a different branch).
Thanks for your time!