A first look at React Query

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
Search for a command to run...

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
Nice! It's such a wonderful tool, happy to see you are using it.
React Query is super cool.
I came across it a long time ago but used it extensively in the current project. I am completely blown away by the power of this lib.
It's so powerful!
every-time I find some new feature and it just blows my mind 🥰
Love the article, Chris! And love the Pokemon~
P.S.: Are you playing the new Pokemon Legends game btw?
Hey Victoria! Thanks, React Query is just amazing.
unfortunately not yet, keeping away from it because it will suck up to much time 😂
Hahaha wise move, yea the game definitely took up a lot of my weekends these days Chris Bongers 😂
It really is an amazing library 🤯
Most of you know me for my consistency, a golden arrow in my blog series. I've written 1000 articles in 1008 days! Almost an article a day, and my honeymoon was the only holiday I ever took. I'm super proud of this achievement; it has been a fantasti...

It's not the first time I'll be talking about community. I think it's an essential aspect of any successful tool. This shows in my previous explorations of Astro, Medusa, and now Vendure as well. All these products thrive in a super open, welcoming, ...

The cool part about Vendure is how easy it is to set up and how abstract each layer is. Basically, we get the following elements: External database Server Worker Admin UI Frontend While this is amazing, it also brings a bit of complexity when it co...

The previous article looked at customizing Vendure on a data and process level. In this article, we'll look at customizing emails, as they are often a big part of a webshop system. We'll be looking at two different layers of customization for customi...

Even though Vendure is a pretty significant project out of the box, in some cases, we might want to go in and modify some elements to work to our specific use case. In this article, I'll take a high-level look at some elements we can customize within...

State management can be a bit difficult in React, the way you have to deal with data, make sure it's cached, re-fetching it when needed, and the list goes on.
Luckily for us, this is exactly where react-query comes in. React query can handle all those and many more things for us.
For this first example, we'll build a list with Pokemon names. When we click on one of the names, it loads that specific Pokemon's details. The first time you'll see it will show a loading indicator, but on a second return, it's neatly cached and show the Pokemon right away.

Let's get started as it's easier to explain as we go so you can see what will happen.
First let's create a new React project:
npx create-react-app react-query
Then we'll need to install react-query:
npm i react-query
And while we are here, let's also install axios to handle requests for us.
npm i axios
That should give us a great starting point. From here, you can open up the project in your favorite terminal.
We'll have to wrap our app with the QueryClientProvider to use react query.
To do this, open up the App.js file and modify the app to look like this:
import {QueryClient, QueryClientProvider} from 'react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<div>Our app</div>
</QueryClientProvider>
);
}
Instead of this div, we want to render a list of Pokemon that the user can then click on.
We'll use a state that will contain the Pokemon that was clicked, so let's start by modifying our code to look like that.
function App() {
const [pokemon, setPokemon] = useState(null);
return (
<QueryClientProvider client={queryClient}>
{pokemon ? (
<Pokemon pokemon={pokemon} setPokemon={setPokemon} />
) : (
<PokemonList setPokemon={setPokemon} />
)}
</QueryClientProvider>
);
}
We defined a state and passed the state to either the Pokemon component or the PokemonList component.
Let's start with the list. First of all, we'll need a function that will be able to query an API.
We then wrap that query in a useQuery hook so react query can handle all the caching.
function usePokemonList() {
return useQuery('pokemon', async () => {
const {data} = await axios.get('https://pokeapi.co/api/v2/pokemon?offset=0&limit=50');
return data.results;
});
}
The first element that we pass to the useQuery hook is the key for this query. In our case, the key is pokemon.
Then we fetch 50 Pokemon from our API and return the results.
And yes, this simply wrapping of code will make sure react query does all the hard work for us.
Let me show you how we can use this:
function PokemonList({setPokemon}) {
const {isLoading, data} = usePokemonList();
return (
<div>
{isLoading ? (
<p>loading...</p>
) : (
<ul>
{data.map((pokemon) => (
<li>
<a onClick={() => setPokemon(pokemon.name)} href="#">
{pokemon.name}
</a>
</li>
))}
</ul>
)}
</div>
);
}
We use the Pokemon list function we just created in the component above. We can extract isLoading and the actual data object from it.
Then we return a loading state while it's loading, or else we render a list of Pokemon.
When the user clicks one of the Pokemon, we invoke the setPokemon function to handle the state.
Now that we have our list, let's work on the Pokemon component. This component should fetch a single Pokemon based on our state.
But before we do that, we should create a new function that can request the API for the details.
function usePokemon(name) {
return useQuery(['pokemon', name], async () => {
const {data} = await axios.get(`https://pokeapi.co/api/v2/pokemon/${name}`);
return data;
});
}
This is similar to what we saw in the list, but we pass an extra attribute to the key property. This will make this query unique for just this Pokemon request.
Let's move on to the actual component:
function Pokemon({pokemon, setPokemon}) {
const {isLoading, data} = usePokemon(pokemon);
return (
<div>
<a href="#" onClick={() => setPokemon(null)}>
Back to the list
</a>
{isLoading ? (
<p>loading...</p>
) : (
<div>
<h1>{pokemon}</h1>
<img src={data.sprites.front_default} alt={pokemon} />
</div>
)}
</div>
);
}
Here we use the function we just created and again show loading while it's still loading and render the Pokemon and an image once it's done.
And there you go. This is how easy it can be to leverage react query to do all the heavy cache management for us.
I set up a Code Sandbox example you can play around with.
Note: If it's already cached, try to add
?v2to the single Pokemon requests.
Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter