Complete Intro to React, v8

Performance Optimization with React Query

Brian Holt

Brian Holt

SQLite Cloud
Complete Intro to React, v8

Check out a free preview of the full Complete Intro to React, v8 course

The "Performance Optimization with React Query" Lesson is part of the full, Complete Intro to React, v8 course featured in this preview video. Here's what you'd learn in this lesson:

Brian demonstrates optimizing the application's performance using React Query by caching pet details that have already been requested. A student's question regarding what happens if fetchPets throws an error is also covered in this segment.

Preview
Close

Transcript from the "Performance Optimization with React Query" Lesson

[00:00:00]
>> So, talking about a couple of things here, it's useful that this isn't a separate file, because now this is super easy to test, right? This would be useful outside of React Query, right? This is just returning a method that if you call and you give it the correct query key, it's gonna give you back the correct response, or it's gonna give you back the result of a response to an API.

[00:00:22]
Also cool, right? So that's another thing I appreciate about React Query, is it makes all the individual async parts of your code individually testable. It's always a positive thing. Okay, so let's go use this in Details now. So we're gonna import ( useQuery ) from '@tanstack/react-query', and import fetchPet from "./fetchPet".

[00:00:54]
And we're gonna say up here, const results = useQuery. So this is how useQuery works. We're gonna give it a key of what we're requesting. So the first one we're gonna give it is the general overarching term. This is the details type of request. And then I'm gonna give it the id.

[00:01:21]
This is the query key that's going to be provided to fetchPet.js. So when I'm pulling off the queryKey right here, that's where I'm getting the key to make the correct id, right? It's coming from here. And then I give it this details. This could be any arbitrary caching key, right?

[00:01:43]
This is the same sort of idea of what you provide to Redis, or Memcached, or something like that, right? So this is good basically say, all right, store it here in your cache. So then it knows later, if I request the exact same key later, I'm gonna get the exact same response.

[00:02:01]
It's not gonna go fetch that from the API again cuz they gave it a cache time of infinity. Okay, and then I say, if you don't have that in your cache, run this. If you don't have details five in your cache, run fetchPet, and it'll go get it for you.

[00:02:26]
Now, we have results. That's gonna be the result of whatever I have. I get to write this code that looks very synchronous, right, which is super cool to me. The first time this comes back, it's not going to have that cache, right? So it's going to give me back something.

[00:02:45]
Notice I did not await here, you can't await in a render function. So it's gonna give me back results.isLoading. And I'm gonna say something like, return, div className = "loading-pane". Freudian slip there. h2, className = "loader". And I just give it something that you want to spin. I gave it a spiral.

[00:03:26]
Put some sort of emoji there, it'll just spin, right? So if it's loading on first load, it's just gonna show that first, right? This is awesome because, Now we don't have to have these big complicated things, like all right, if this is happening to this, if this is happening to this.

[00:03:48]
Immediately, the user is gonna see something loading. And then as soon as fetchPet completes, it's going to go and rerender with the correct information. So it's short circuits here, right? And I don't have to worry about after this. I can now assume past here, pet is available and pet has loaded.

[00:04:07]
So I can just say, const pet = results.data.pets[0], like that. Cuz that's the shape, it comes back from the API. And now I can say, div className = "details". Another div, h1, pet.name. H2, (pet.animal), (pet.breed), (pet.city), (pet.state), I don't need those dollar signs. Okay, Then we'll put a button there.

[00:05:19]
It's pet adoption site, right? So you're gonna say, Adopt (pet.name), a call to action. And then we'll have a paragraph underneath that with the pet.description. Okay, let me make sure that I'm not out of line here. So if I click on Luna, you saw that I had a nice little spinner there for just a hot second.

[00:05:50]
If you want to see that a little bit longer, it just looks like this, right? Okay, And now, we have this button that doesn't do anything, but we have a more detailed pet page, right? But how cool is this, right? So I get to basically treat this like a synchronous hook, but it's fetching from an asynchronous API.

[00:06:23]
And then I just have to do some bifurcation of like, if it's loading, do this, there's other things here. There's results., and you can see here, there's isError, isFetched, isFetchedAfterMount. They give you a bunch of flags that you can check, or you can also just look at status, right, which will have a text if you wanna do more of a switch statement or something like that.

[00:06:49]
If you wanna manually yourself, call refetch, you can just say, results.refetch. And this will actually go back out to the API if you think it's stale and refresh it. There's a bunch of stuff. React Query is a really cool piece of software. We're not gonna really scratch much more than this.

[00:07:05]
But honestly, this is pretty cool already. I think this is better than a useEffect, right? This is more readable than to useEffect according to me. And here's the cool part, again, looking back at our network tab. Sorry, I'm gonna click on Luna, you can see here I got the pets?id here.

[00:07:23]
I'm gonna go back, And I'm gonna click on Luna again. Notice that it does not refresh Luna, right? It's keeping that in the cache. But if I go back and click on Bunna, see the pets?id there, 2, right? But I'm gonna go back to Luna, no refetch. Pretty cool, right?

[00:07:50]
Notice that every time I go back to the homepage, I am refetching the general pets search page. That's because that useEffect is always running, right? Doesn't care that it's already fetched that before, it's just always rerunning that. So I don't know, this is pretty compelling to me. This is compelling to me enough that I basically always use this when I'm using React.

[00:08:19]
Yeah, I'd rather write this in effects. So yeah, I use this all the time, yeah.
>> What happens if fetchPet throws an error?
>> If it does, Then you'll get results.isError, right there. And so I'm not being defensive here, but you would have another thing here, results.isError. Return, Okay?

[00:09:03]
>> [INAUDIBLE]
>> No, so it actually tries to refetch three times. So it's gonna make an assumption of, maybe there's an intermediate issue here. So it has some exponential back off. There's a bunch of stuff that's really configurable. But by default, it tries three times with exponential back off, and eventually, it'll show an error state So then I ended up with, no, right?

[00:09:29]
React Query has some really cool stuff built into it.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now