Display loading, error and successful query state using React Query Type Narrowing

Tomasz Ducin
InstructorTomasz Ducin
Share this video with your friends

Social Share Links

Send Tweet

React Query will narrow the type of your query results depending on its state.

In this lesson, you'll dig into the types under the hood, and then conditionally render various messages based on the state of the query.

[00:00] Use the object returned by the useQuery hook. And we're going to destructure 2 more properties out of it, and these are the is loading and error. What we have for now is that the data could have been received already or not loaded yet, which is represented by undefined. [00:20] The error could have occurred or there might be no error represented by null. And finally, the status of the query which says that it is either still loading or if it has succeeded or failed, it would be is loading failed. What is important is that not all combinations [00:40] of the potential values of all these properties are possible. For instance, if we are initially loading the data and we have succeeded and we have the employee array over here. It's not necessarily possible that we would have an error at the same time [01:00] because in the initial case, it just might not be possible. It might not make sense. So for this reason, React Query is using TypeScript unions of object types to explicitly define what are the valid possibilities. So let's take a look at how it's defined, and we will [01:20] take a look first at what are generally the possibilities. So these are defined by the query observer base result type. So here it defines that generally data could either be the data or no data yet. The error could be either the error or no error yet and so [01:40] on and so forth. But if we scroll down, we will see just the explicit possibilities. So for instance, the query observer loading results determines that we initially have the loading, which is true. So we have no data yet, and there is no [02:00] error yet, but we are loading. Of course, we have more properties, but these are just the important ones for now. And we have also query observer success result, which means since this is success, we do have the data and we don't have the error. And since we have a success, we are not loading [02:20] yet. So the is loading is false. But there could be also an error state where the error is there, we don't have the data, and we are not loading because, well, we just failed, or that there was a refresh error, which means [02:39] we did have the data before and now there is an error. And since the error happened, we are not loading yet. So depending on whatever if statements, any conditions that we're going to execute, TypeScript is going to narrow the types accordingly. So let's [02:59] move back to the employees page and let's use the properties discussed. So we're going to create a couple of if statements to check-in which status we're in. So if we are in the loading state, let's just return a simple message defining that we are still loading or if we are in the error state, [03:19] let's also display what is the error message. So here we're going to use the error dot message property. Unless we specify that otherwise, the native JavaScript TypeScript error prototype or interface is going to be used. So you could think that [03:39] since we are in neither loading nor the error state, so neither of these early returns has been executed, then, well, we have excluded all these other cases so that data should actually be here. But we can see that within the data property type, undefined is still there. So at this [03:58] point, we need to dive a little bit deeper into the different properties that represent the fact of loading. So we have a couple of them. Is loading is one of them. There is also is pending and there is also is fetching. So they all relate to data loading, data fetching, the data that is pending, but they [04:18] have slightly different meanings. We're going to dive deeper into it in the next lesson. But most of the cases, what we want to use is the is pending property, which basically means we have no data loaded yet. So we have nothing to display whether we are already, like, fetching some data, there is a [04:38] request ongoing or not. We have no data yet. So basically, there is no way for us to display anything over here. And if we have excluded is pending and error, then we can see that yes, undefined is being totally removed from here. So what we can do is to get rid of this conditional rendering over here. So now [04:58] let's take a look how does our component actually behave. So let's refresh it over here and we can see that the employees list over here is displaying correctly and it's also showing the loading message over here. So let's see how would this behave if we have [05:18] triggered an error. So for this reason, I'm going to use the browser dev tools. They block request URL or block request domains. So just click somewhere over here and we have enabled the network request blocking. This is a very useful feature. And we [05:37] have just made sure that local host 3,000, employees page 1, this is going to throw an error whenever we want to request it and the whole network request blocking is turned on. So I'm going to refresh the page, and React Query is going to shoot a little bit of retries. [05:57] So let's just see how this goes. I'm refreshing the page, we can see that the first request has failed, the second one, the third one. And finally, when the 4th one is going to fail, we can also see that the failed to fetch error message, which comes from here is displayed. So this is the way we can differentiate [06:17] and display different content depending on what is the state of the query. And don't forget to turn off the enable network request blocking. If you do, this triangular exclamation mark is going to remind you about that. So just turn it off and now network is going to work normally.