React Query Tutorial with Typescript | Part 1 -- Queries

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hey guys and welcome back to uh my youtube channel and today we're going to be starting part one of my react query tutorial if you're not familiar with what react query is react query is pretty much a data fetching library that kind of hopes to make your life as a front-end developer a lot easier by kind of trying to manage the fetching part as well as caching and synchronizing as well as updating service date on your client side of course you can just use uh the usual kind of fetching library such as fetch axios or graphql requests but what react query tries to do is it kind of kind of tries to become like a wrapper around those fetch libraries to try to make your life a lot easier some of the benefits you get by using react query is pretty much you get caching out of the box which is kind of one of the hardest things to really do in programming at least in the front end application you also get kind of deduping multiple requests you can kind of uh better your prop drilling by instead of doing some prop drilling by passing the data to the sub components you can actually just use a cache query so like any mounted component then becomes an observer and it's able to just query the cache data as opposed to having to be passed down through the prop tree uh you can actually know when data is stale and so when data is still you can make another refetch request you can in the background make fetch requests you can use pagination queries you can use things like infinite queries mutations you can manage the cache directly it's a really really powerful and useful library so why might you try to use react query as opposed to other kind of data fetching libraries that do the same thing such as use wsr and kind of apollo client at least personally those are the two other ones that i've used and i've kind of implemented all three of them in different applications and i've honestly found that the react query development flow is probably the best out of the three it's also a little bit weight not a little bit but way less bloated than apollo client and i know that uh one of the kind of selling points for apollo client is cache normalization but i found that i necessarily don't really use that too often and it kind of just confuses me and uh it gets a little complicated when you're using it because i tend to use next.js a lot and it gets a little complicated when using apollo client with uh server-side rendering but essentially react query i found is kind of just the best development uh process it has dev tools it has some of the best documentation around it's it's been really fun to use and learn so let's get started so the first thing i'm going to do is i'm going to start out with my next js kind of front end so react query as you can tell by the name it does require you to use react so this would not necessarily work for vue or other applications and that's because it relies quite heavily on react hooks but let's go ahead and start kind of just create a template from my next.jsts frontend project and then i'll put a link and as well as a card to the video of where i kind of go ahead and implement that project and let's make this just react query uh tutorial and um uh let's just do react query tutorial and let's start that out let's go into the react query tutorial and open it up in vs code so first thing i'm going to do is i'm going to open up my terminal and i'm actually going to zoom in a little bit so you guys can see a little bit better and then uh what i'm first going to do is of course i'm going to go ahead and add the react query library and i believe this will also install all of my uh dependencies from my package json as well and once you have that installed i'm going to go ahead and start cleaning some things up so right now we don't need the kind of the tester components that i had before so let's get rid of that we'll keep components just in case we need to create that library again and we're ready to go and just as a quick kind of just reminder this is just let me just change the project name and again this is just an xjs application it's using react 17 um it's going ahead and using a couple of eslint prettier configs but other than that it doesn't really have anything else installed um and let's just make sure so we can see here react queries installed and we're ready to start so first thing i'm going to do to get started is i'm going to actually go ahead and within source i'm going to create a couple of interfaces or at least one and the interface i want to create is so i'm going to create a lib file and interfaces file and i'm going to create an iperson and we're going to be using this throughout our kind of this tutorial for the queries at least and what i'm going to do is i'm going to just export interface i person and that's going to have an id which is a string it's going to have a name which is also a string and an age which is a number and cool we're ready to go with that and then the next thing we're going to do is within if you're familiar with uh next.js pretty much what api does is it allows you to kind of build a backend within your front end application so that's the reason i chose to do this i didn't want to necessarily go out of my way to kind of create a back end for this tutorial so next guest is nice because i can kind of just create uh routes with an api and then i can use that to actually be fetched as if it were a back-end server itself so let's go ahead and create our person uh api endpoint and the way i'm going to do that is i'm actually going to create a person folder and within this folder i'm going to do index.ts so pretty much again if you're not familiar with nexjs what this means is uh for the i can actually create person as part of my api as part of a route but if i create person as a folder with an index file this pretty much just tells nexus like hey this is going to be the route so anytime i try to access slash person it's actually going to call this index route so just a heads up on that and the way we're going to do is we're going to actually uh implement it in this way and what we're doing here is we're pretty much just getting some typescript stuff uh we're exporting our default endpoint and what this is doing is pretty much just returning a 200 with this kind of pre-configured person object with id of one named john doe age 25. and in this part i'm going to be focusing on query specifically so we're going to be doing a lot of get requests and so the next thing we're going to do is since we have gone ahead and installed react query the next thing we got to do is actually go into our application and we got to make sure that we actually wrap our component with the query client provider as well as provide this react query client to our application so pretty much what this is doing is pretty much just saying hey let's add a provider to the top level of our entire application so that any kind of sub component can have access to this react query client and with that the next thing we're going to do is similar to how we created our api here we're going to create a person page and within this person page i'm going to go ahead and create index.tsx and just kind of create a simple react page here or an xjs page which is a functional component and i was going to say is just person for right now and then let's go ahead and start our development server and make sure that everything is working by going to localhost 3000 um did that not open up i guess it did not oh yeah it just took a little while and let's see here it should open up a bunch of next js stuff because i'm just using kind of the default index page from right here and then if i go back to here and then we go just to navigate to slash person we should get person so we're ready to start defining this page so let's go ahead and actually uh add some things to this person page and uh usually what i like to do is i like to kind of paste the code and then kind of walk through what is going on and we can kind of discuss why i did that or why it's done in that way so for right now we're gonna start off this person page with a quick kind of so if you're again so how do we kind of use react query and react query in my eyes have three kind of main points there's queries there are mutation and and then there's uh queries cache stuff so those are kind of like the three main concepts and then you can kind of uh work with all three of them together especially like with the cache and queries cache and mutations and everything like that and to kind of give you guys a quick definition of what a react or what the query part of the react query is queries is essentially a way to fetch data from an asynchronous source of data uh usually like a server backend or something like that and you can actually tie this query to a unique key and then this unique key acts as kind of like the cash key for imagine the cash is a key value store and whatever so for right now in this example we're using person as our cash key and so whenever this query is executed it gets added to the cash as a person as a key and so any time then we go and do a query again with this specific key it looks into the cache and like hey does this already exist it does goes in and caches and gets that cache value as opposed to going and refetching the entire uh query so that's pretty much what it is and this uh a query doesn't necessarily need to be just a get request for this example we're going to be using it as a get request but you could actually also make queries using a post request and the reason for that is you could actually just make a post request as your get request or you could you might be using graphql but you want to use the fetch library so just be aware that you can also do uh get or post requests for queries so what are we doing here so pretty much what we're doing is let's just change this really quick and so you can see so usually you can kind of get result as a use query result and it's giving me this error because i'm not necessarily using it right now but within this result there comes a bunch of separate types of objects that you can actually access within this result and the three that i'm kind of going to talk about right now i'll introduce a couple in a little bit but the three main ones are status so pretty much if we hover over status you can see that it kind of is a string of kind of four different types of possible states of your query so it could be idle it could have an error it could be loading like it's actually fetching or a success it's done and everything returned okay then you can actually access an error object and this error object is pretty much the expected uh error from whatever your query fetch function so right now we're defining our query function as just a quick fetch to the api and then just returning the json of that return the the body of that and then data which is the data that's actually returned if it actually returns successfully so data right now will be res.json and pretty much then what you can also get is you use this use query result which is just typescript stuff and pretty much what it expects is what is the type that is expected from to be returned from your query function as well as this could be all the possible errors that are expected so right now we're just using it as error but let's say for example you can kind of create custom errors and you can do maybe like a 404 not found error or different kind of error interfaces or different error types next let's take a quick look at use query and pretty much use query is a hook that react query provides you to actually execute a query and it can kind of come with four different uh type things that it's expecting here and these are uh pretty much the t query function data and what this is is pretty much what is the expected output type of your query function error again it's just what type of error is it possibly expected from your query function uh t data is an optional field that you don't necessarily need to provide it but what's cool about it is it's what is your data eventually going to be so this is usually used for uh select which i'll go into here in a little bit and then t query uh or the query key which is pretty much just uh the type of your query key i usually just type just to kind of just leave this alone but you can kind of either pass like an array or um like make it something else like that and just to clarify that uh query key there's usually two types of expected keys so if we go to react query documentation with a query key um usually it's either a string key or it's also it could be array key so what is a string key essentially what we have there is just a quick like expect this string of like to do's or something special or in our case it's person or you can pass an array key which then it gets a little interesting because array keys you can provide uh something like an individual with like let's say a number so for example id is five you could also pass like objects into this so imagine this array is just kind of like a way for it's an object that can be act uh used as a key uh for your uh query cache so it's really cool another thing to keep it note is that they are hash determinantless deterministically and uh what that means is pretty much like if you use the query like this it will actually go ahead and keep like undefined objects first uh but it doesn't necessarily kind of restructure this but that gets a little bit more advanced we don't need to worry about that for right now but what we can do actually is we can go back here and since uh we kind of understand that a little bit better we can actually provide those fields here and we can do things like iperson and string just to kind of make it a little bit more typey um i believe it usually it can infer kind of um what these two are by your actual what you uh return as well as um the whatever the query key that it sees that's present and yeah so then we have the query key we have our query function that we define here which is just a quick get request and then the next couple of things that we should look at is so for this status as i mentioned uh if we look down here we can see is if status is equal to i should change this to loading then we want to present something that's loading if there is an error present or we could do if status is equal to error then what we could do is we would um oops i need one more error and if we do something like that right if status is equal to error then we would uh return this and then we also would need to make sure that uh error is present because right now it's complaining that it could be possibly undefined but if status is error and then we would display a message like that and then if not everything is all good then we go ahead and display our data but instead of using status and uh equals equals and kind of like doing these types of checks we could actually what uh react query provides us within this use query is a couple of different objects that actually kind of give us that specific error as a variable so for example is loading is pretty much reflective of status equals equals equals is loading or you could do is error as well and then there's also is idle which means it's like currently not doing anything or is fetching which means it's currently working in the background right now so those are a couple of the really cool variables that you can do so once we kind of add those instead of doing is status is this we could actually do is loading and then the same thing here if status is error we could actually replace that with his error and then another kind of cool thing is we could also there's also is success as well meaning that like everything is uh everything went through correctly but we don't necessarily need to worry about that for this and then what we can then look at is how the caching stuff works so let's go ahead and into our api route here that we're calling before what we're going to then do is i'm just going to add a quick console log of uh getting person meaning that we actually went ahead and called our backend and then what i'm going to do is i'm going to open up our application again and now you can see here um again let me try to zoom in a little bit what you'll be able to see is that we actually have this uh one is john doe and i pretty much what is being returned from our index.js here right um and you can see here that it's getting person so anytime i navigate to this page or anytime i reload the page um it will fetch this and if another cool thing to note is uh react query has this uh refetch on window focused that is a default true and what that means is pretty much if i am using our application but i go to another tab if i go back to the tab it actually re-fetches the query if it's stale so for example right now you can see that uh i go here and if you can check here we have one two three four five six seven getting persons if i go back you can see now there's eight and this is going to be useful to kind of show how caching works within uh our next.js application and one of the really cool things that we can actually add is a dev tool kind of system that reacts query actually provides for us without having to install any other library so react query actually provides react query dev tools that you can kind of implement into your application and then you can set initial is open to false meaning like i don't want this open naturally but if we now navigate to our page here you're going to see this symbol here this little flower and if you click on it you actually get a react query cache uh kind of dev tool so you can actually go ahead and see what's going on within your react query uh provider and your client so what you can see here is pretty much we have one since we executed the person query we have this is a look into our cache we have a person cache and it's currently stale but you can see here if we uh actually look into what's in here you can see that the data that is cached is the one john doe which is the cache data from our api request and then it kind of comes with a bunch of different options here so for example cache time how long is this actually gonna live in the cache if it's an active uh the query what is the query key what is the query hash some initial state stuff um and that's kind of like some of the default options and let's actually go ahead and see what happens so one of the kind of things to note is the important default for this cache is that uh the stale time which is an option you can pass to either your query or to your query client is normally set to zero so what does that mean it means that any time you execute a query it immediately becomes stale and this is fine um but pretty much that defeats the purpose of having a cache because as soon as you execute execute it it's stale so that any time i go back to this person page instead of it actually calling the cached value it's going to go out and refetch my api route which you can see by this getting person log and how do we fix that and the way that we go about fixing that is if we go back to our application and we go to our person index page here let me close out the other ones oh didn't mean to close that one what we can actually do is we can actually provide a options um and within this options we can actually provide a couple of things so there's a couple of the most useful uh query options that i found is there's still time there's cash time i've actually never had to use this because i just kind of just leave the default but if you want to play around with it you can make it for example cash time infinite meaning that it'll never leave your front end cache another one is the select key and select is pretty interesting because what select lets you do i kind of have it defaulted or kind of implemented down here is you can actually pass in whatever the uh the return from this so let's say for example this returns our person object we can actually pass this in and then what we're going to do is we can actually instead of passing back the whole object you can actually just pass in or pass back the specific just like a maybe a specific field that you want from that object and then select as you can see here it's going to give me an error because it's expecting the eventual type to be person so what i would need to do is to change this to string so if i change the string then you can see that the select is cool and it actually works but um i'm not going to do that for this i'm going to change those back but just to know that's kind of one of the really useful things if you're using um fetcher axios and you only want to get back a certain amount of uh fields from whatever is returned and then another kind of useful thing is um i think that's kind of it actually oh yeah no the other useful thing another useful option is that you can actually have this enabled option and but we'll get into that here in a little bit because what enabled it lets you do is it lets you run deterministic queries so or determine queries which is really powerful so like if you have to wait on something but we'll get back to that here in a little bit so yeah so you can see here if we go back and we look at our cache um it's currently being invalidated right away so let's go ahead and actually change this to make the stale time a little bit longer so what i want to do is i want to make the stale time of five seconds and this is expecting milliseconds so what i'm gonna do is five times a thousand so that's just five thousand which is five seconds in milliseconds and then let's go back to our page so here you can see now that our request is actually fresh and after five seconds it becomes stale so if i refetch the page you can see here we got to get person right so let me actually open this over here and let me so there's currently three right now if i navigate away and go back to it it's fresh but if i quickly do it again you can see that it's no longer kind of requesting it because it's actually getting the cash information so go back here cash getting person if i do it again there's only five if i do it again really quick before it gets stale oh that was too slow but like you see fresh and then i can keep going back and forth because of that refetch on window focus and you can actually disable that but i kind of just like to leave it but you can see that's kind of how the cache works and so let's just add a little bit of last clean up to our uh page over here and what i pretty much am doing is you can actually define a function so for example here i'm actually going to move our query function into its own separate function called fetch person and then here what we got to do is we got to make sure that since we're using fetch for this tutorial if you're using axios or graphql request it does throw errors automatically so you wouldn't need to necessarily do it like this but what i need to do is since we're going to be using fetch we need to make sure that our response is actually of response.okay meaning it returned to 200 and if it did then we return res.json but if not we actually have to throw the error within our uh kind of our query function and the reason for that is because react query functions need to have its error thrown in order for it to know that it's an error state as well as to actually provide that error to this error object so that's all i did and then so instead of actually defining it within our query function here i just pass it in so fetch person is passed in like that again this is the same thing just as an example of just how to use select and everything should be good to go as in terms of just regular um query functions and the cache so let's quickly move uh this stale time kind of configuration so let's say for example you want all of your queries to kind of have a five second query uh cache time so what you can do is you can actually add into your query client here you can actually pass in a uh default options so you can override the current default options and i actually need to make this an object so let's make this object default options and then you can actually pass in a query um options wait what's going on okay query queries like this and then what we'll do is we'll pass in stale time of five times a thousand and then another thing you could do you can also have mutations but we'll get into that in the next video but pretty much what this will do is any query that is executed make it sure that it has a five second uh cache time or a five second stale time before it gets stale next let's look how to do queries with parameters and what we're going to do is first we're actually going to go ahead and since we created this person i'm going to create a parameter expecting api route and i'm going to do that by xjs again slash id it means like just take the the whatever the next part of the route is so like slash person slash one two three id will be one two three and so let's quickly define it here and what we're doing here is same thing as before but instead now we're actually getting this id from uh the url and then we're going to just make sure like if it's the type of id a string meaning that it's the correct type then we return a 200 and we're going to return the id that's being passed into the url but then we're also just going to pass in the name john doe age 25 and then if it's not then we return to 500. and then what we're going to do next is we're going to go ahead and actually create this page as well and creating the dynamic page is similar so pretty much all you got to do is idtsx so this will render a page anytime you do slash person slash one two three it'll render this specific page and let's quickly define a couple of things and we're kind of gonna go over this a little bit quicker since we kind of understand the basics of use query but pretty much what we're doing here is we're defining a function called get person by id which id is going to be string string array or undefined that's pretty much what url params are kind of the typing that it gets from uh the url using next and then we try to make sure just a little bit of things like if type of id is string then we actually go ahead and we run our fetch to api person id which we'll call that new api we just defined and we return that json if it's okay so i actually need to make sure that if res that okay here then i return it but then if not then i got to make sure just to also throw another error um of uh error fetching user with id let's just do something like that so this is again because we're using the fetch library fetch doesn't naturally throw errors by itself so we need to throw it ourselves and then in the person page what are we doing here we're getting the id again similar to how we did it in the api route we're doing it here we're getting the id from the url and then here we're using use query again but we're actually passing in an array key and this array key is going to be a person but it's actually going to be also the id that's in the url so this means that person slash one two three is going to have the query key of person and one two three meaning that it's a unique query key as opposed to let's say we use different ids for different pages then they'll each have their each unique uh query for that person and then since we're going to be calling uh a function with parameters before in this index.cs you saw that we just passed the function without necessarily having to call it in react query version 3 they kind of want you to use these inline function calls so you'll do just define a quick inline function and then you call your actual function and pass your parameters and then the next kind of important thing that i kind of talked about the option of enabled and what does enable do so if we look at this quick definition enable pretty much stops the query from executing if it's set to false so if enabled is false means like don't execute i don't want you to run so that's kind of powerful because then we can create these things called dependent queries and i mistyped there and dependent queries means like hey wait for this to actually be true before i execute so one of the things is with react right you might have uh certain variables that are undefined during page load or during rendering and you don't necessarily want to call out to your api route with undefined as id because you're going to look at in your database and be like wait this is undefined doesn't exist it returns an error so what we can do is we can actually set this enabled to be hey wait for id to actually be present within the page before you execute and so once that's executed then we actually get all this other information right and so then we're going to have this loading time similar to how we had it in our other page it's pretty much the same everywhere else it's just that now we're actually calling um this unique query key with uh with parameters and down here you can see i also have kind of like another example if you do need to pass in multiple parameters you could easily do that by just kind of chaining it as we kind of talked about how curry keys worked before and if we quickly go back to our application here we can quickly see if i go to person slash one two three um this should load a page right so you can see here that we have the one two three john doe and twenty five and here's our cache where we have person of null is stale because it kind of tried to execute this use query of when id was null and it doesn't find anything but then we also have this one two three but you can see here that it's also being fresh for five seconds because it uh of that uh default options that we passed into the query client creator in our app page and what do i mean by kind of avoiding prop drilling so let's go ahead and actually create a person component within our component here and um let's just do it like that and what we're going to do is that's not a person component let's just copy this over here and pretty much what i then need to do is from our index here i need to export this function since we're just going to be reusing it for this component because i want to show you guys how you can kind of get away or just use this really powerful tool of uh the cache queries to kind of avoid prop drilling so pretty much as you can see here what we're doing is we're actually calling pretty much the exact same query as we were in our index.tx right so like if we look at it it's almost identical it's pretty it is identical if you call it like that um i just have this kind of uh commented out thing so we can get rid of that but then what we can do that's really cool is we can actually go to our index page and then uh here under link what we're going to do actually i'm going to kind of just create something just to kind of quickly show you guys is uh just let's do person component and then i can actually import the person component and um did i not save this exporting yep so that should be able to be imported okay so then once we import that let's see uh this is still not defined i don't oh there you go okay now it actually imported so when we do that and then we go back to our page so what i want to quickly show you guys is like yeah so you can see getting person by id it's only running once but if i go to slash person so if this were to be a non-cached query we would actually be calling our api twice so if i quickly go to app and let's just um let's just get rid of this meaning that we don't want to pass anything um just so i can kind of show you guys when i reload this page you can see that i'm actually since the uh query is stale it calls it twice but if i actually make sure that our um stale time is valid for five seconds that means that any component that is being rendered or currently loaded on this page that is listening or observing this specific query it will use the cache value if it is cache and fresh so you can see here you can see now that we have two observers and so what that means is that this person we have two different components that are listening to this query so we have the overall page that is right here and then we also have our person component but you can see that we only only call it once because it's fresh after the initial call and then something similar to here is that if uh you kind of navigate and there's no components that are loaded with it you will see that it will actually um make it inactive which means that it's just it is still in the cache but it's inactive and uh next time we go to the person page it will call it no matter what and it'll stay inactive until the cash time hits uh whatever the limit is and then if it does then it will actually um uh remove it from the cash and yeah that's kind of a quick introduction to react queries query part and uh the kind of the last thing i wanted to quickly touch up on is the query retries so react query handles retry logic for you and the way that it does is that it'll automatically retry the query if the queries request has not already hit the maximum consecutive requests which is defaults to three you can play around with this similar to other things you can make it false so make it never retry you can also make it so that you can change the amount that it retries you could also maybe add some custom logic make make it infinitely retry as well as by default i believe that the retry delay has some kind of back off coefficient so here you can see it starts at one second and then it kind of doubles so uh there's like one second it fails again two seconds fails again four seconds fails again and then it'll stop if you're if it's set to three if not it'll keep going until six so that's really cool um another thing that's kind of interesting to note is that use query is actually uh parallel by default what that means is so for example if i have a page where i want to run multiple react queries using use query i can actually chain them together like this and they will asynchronously run meaning that the this uh this query will not wait for the result of this query they'll just kind of go ahead so like let's say for example this one is like i want this to return i to do's for uh for everybody right um or just a list of to do's it could do something like that and it'll run in parallel or as we kind of touched upon is that you can actually have dependent queries which we looked at in here where we actually run once we have this enabled so once id exists so another thing you can do right you could do like cost id is actually equal to use query of um something of like get query uh or get user id and then what you can actually then do is then uh you can execute this query which will return the id and then if you set enabled to wait for it that means that this uh this query itself will not execute until this is defined meaning that this query has finished so that's kind of a quick way to run dependent queries and those are the two main types it's either parallel or dependent so also just note that and yeah that's a quick introduction to queries and react query i hope that you guys have found this useful and kind of see the power that this library gives you and just how easy it is to really use and this is kind of the most basic example using fetch you can use axios you can use graphql requests you can use a bunch of different things to kind of customize it but this is kind of just a query part in the next part of the video i will be talking about mutations so i hope to see you guys there and i hope you guys enjoyed this video so uh leave a like if you did comment if i missed anything or if you guys uh have any questions or anything like that and if you guys did enjoy it uh make sure to subscribe for more content and i'll see you guys in part two you
Info
Channel: Leo Roese
Views: 4,847
Rating: undefined out of 5
Keywords: react, react query, react-query, data fetching, frontend, next, next.js, typescript, javascript, node.js, query, cache, react-query cache, react query cache
Id: KSi7KVc4IDU
Channel Id: undefined
Length: 34min 21sec (2061 seconds)
Published: Thu Jul 01 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.