React Query leveraging placeholder data

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.
No comments yet. Be the first to comment.
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...

Now that we are pretty familiar with the concepts of React Query let's take a look at how we can leverage placeholder data.
We can update the user with as much information as before, showing the loaded data with placeholder data.
Let's take the following example.
In the video below, I've added a delay on the request so you can see the initial data already loading something before showing the actual data.

If you like to follow along, I'm using the result of this article on React Query as our starting point.
The placeholder data will be returned as your data object, so it's important to keep this in mind and ensure they have overlapping properties.
First let's modify the usePokemon function to use placeholder data.
function usePokemon(name) {
return useQuery(
['pokemon', name],
async () => {
const data = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`);
return data.json();
},
{
placeholderData: {name: 'Placeholder'},
}
);
}
This is how it will work, but as we said, we already queried the actual data once, so we might as well use that here.
Note: We only have the name available in this example, and it's also an argument. (Keep in mind this initial query could have more data!)
Besides having the ability to return something directly, we can use a function to extract the correct item from our existing primary query data.
function usePokemon(name) {
return useQuery(
['pokemon', name],
async () => {
const data = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`);
return data.json();
},
{
placeholderData: () =>
queryClient.getQueryData('pokemon')?.find((pokemon) => pokemon.name === name),
}
);
}
We tell React Query to look in our existing cached data and return the Pokemon that matches this name with this function.
What do we have to change in our rendering?
We just have to make sure we are using conditional access to the property we might not have loaded yet.
Or you could opt to show a placeholder for those specific elements that are still being retrieved.
return (
<div>
<a href="#" onClick={() => setPokemon(null)}>
Back to the list
</a>
<div>
<h1>{data.name}</h1>
<img src={data.sprites?.front_default} alt={data.name} />
</div>
</div>
);
In React Query, we not only get placeholder data, which we described above.
There is also a thing called initialData.
On paper, these two are very similar. They can return data before the query is actually done.
However, there are some main differences.
Placeholder data works on the observer level, which means the data is never persisted into the cache. initial data, however, persists in the cache, and it acts as a temporary set of data until it gets updated with the real thing.
The error handling between the two also has some differences. With initial data, the query will be in an error state, but it will be available since the data was already set.
We are also in error state with the placeholder option, but the data is gone since it was only available in the observer.
There is also a big difference if you optimize your loads with stale time, and TKDodo has a fantastic article on that.
If you'd like to play around with this, I've set up a Code Sandbox you can use.
Some things to try:
usePokemon fetch request to a failing endpoint by adding some random charactersinitialData to see what happens in the errorThank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter