React Query in 40 Minutes - Everything You Need to Know About Tanstack React Query

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys how's it going I'm back here with another video and today I decided to bring this in-depth tutorial where I'm going to be teaching you guys everything I believe you need to know in order to be using the react query library for fetching data in your react applications like I've said many times in the past uh this is my favorite solution for fetching data and react and I feel like there aren't a lot of videos on YouTube right now where uh people get indepth uh explanations of all the different different use cases in which react query might Trump all of the other fetching libraries so that's my plan for today's video if you're interested in just seeing some parts of it you can obviously use the uh chapters I put down below and jump to whatever part of the video you are interested in and yeah that's that's pretty much it before we get into the video if you could leave a like And subscribe I would massively appreciate it it will help push my videos to more people and I would be extremely grateful if you could do so so with that in mind let's get into the tutorial [Music] okay everyone so the first thing I need to teach you guys is how to install the library I have here a very simple react application as you guys can see and um it currently doesn't have it installed so I'm just going to open up over here the terminal and I'm going to run yarn add at 10stack um slash react query so this is the library we're going to be installing uh previously it used to be called react query a while ago like just react quy and that's what you had to install but uh now it has the little at 10 stack so that's something I've seen a lot of people actually getting confused because of old videos but as you can see we just installed the library I'm going to delete a bunch of the stuff from here just so I don't have to deal with it uh this is what comes with a boilerplate code from create react app um but yeah so what we need to do is we need to first um tell react that we're going to be using react query the reason for that is because react query is not only a data fetching solution but also a state management solution in my opinion you can very easily use react query as a replacement for stuff like susten and Redux it has a very very nice support for handling and changing the state of your application through the data you're fetching so we need to tell our app that in certain parts of it it's going to have to have access to all of that data that is shared across your application uh just like if you were using the context API and you needed a provider to determine where in your app you would get that data we need to do the same thing with react query so what I need to do is get the entry point of our application which is the index.js file over here where we render our app component and I'm going to uh pass in a provider from react query so to do that we need to instantiate a query client and a query client is something we can get right over here from um I'm going to import from the library we just installed at 10stack Red query and I need to import uh three things first the query client then the query client provider and uh actually I'll just import two for this one because uh I'll use the usequery hook on on the other component but yeah for now we'll just have this too so the query client like I said is us just instantiating like a version of react query in our app and we're telling react that wherever we pass this query client is where we will have access to the cache of react query so that's all information that we're going to deal with later and I'm going to teach you guys everything obviously but just know that you should put this uh however up in your component Tre as you can because we will want to have have access to all the data everywhere so might as well just put it um in the highest uh part right so for now we just create it like this we're not even going to fill anything in this object um then we also need to use the provider so what I want to do is I want to pass in the query client provider over here and just wrap all of our app around with this but obviously since we're passing a provider we need to pass in the client over here and the client is the qu client we just created so now this should be working this was us just telling react that we're going to be using react query now we have to actually use it and for that I'm going to be using um an online fake API uh that uses Json called Json Place holder it's really cool if you're testing stuff uh this is the link to it this is what we're going to be fetching we're going to be fetching fake to-do data uh as an example for this video so if you're interested just go ahead and go to this website as well so what we want to do is I'm going to comment this out because obviously we don't want to just put it there I want to import from uh 10 stack react query the usequery hook now the usequery hook is whenever we're going to fetch data whenever we make a get request this is what we use it will get data from an API and it will handle all the things related to fetching data for you so normally if you're just using I don't know exus or the fetch uh API and you put it inside of a use effect you would have to manually create States for the data the error the stat of the status of it if it's loading or not all that kind of stuff for this case use Query hook does all of that for you and you don't even have to create or use the use effect hook so uh we're going to just create an example over here so you guys can see so I'll just say const I'll open and close curly braces set equal and pass in the used query hook now inside of here we have to put a couple things so the first thing will be a bit confusing in the start but it will make a lot of sense when we start dealing with the cache stuff so query key is basically every time we have a query we need to specify a query key uh a unique query key that will distinguish it from all the other queries we have in our app the reason for that is because when we're dealing with cash and we make some changes to our data and we manually I don't know change the cache we want to change that data in all of the other queries that are querying this specific data so in order to do that we basically pass in the same query key to all of them and react query will know that if one of them have any change then we want the change to occur on all of the other ones as well so we're going to come over here and we're going to give it a query key of too the reason why it's an array is because you can actually pass in multiple query keys and U that's more obviously when you start working with more data data that interact like that interact with each other and there's a lot of use cases as well so now uh the only other thing we need to pass here is the query function now this is where a lot of people get confused because react query is not an alternative for something like ause or the fetch API because ause and the fetch API its main purpose is to fetch the data is to directly just get the data make the request to the API and get the data what react query does is it basically handles all of the other things that you should do after getting the data which is actually way more than you would imagine so um we still have to fetch the data either using axus or the fetch API I'm going to just use the fetch API because uh I stopped using axus I feel like the fetch API is way simpler and it's not it doesn't increase size in our bundle so to use the fetch API for this we're just going to say fetch over here we're going to put in the URL of our API which I grabbed it from here and then I'm going to say dot then to handle the promise I'm going to say res to get the response and I'm going to turn the response into a Json so what we're doing here is we're basically in this function we need to return a Json with the result of this including the errors including the data in itself including everything we're going to return all of this from this function and right now when we fetch the data it first doesn't is actually converted into Json so that's why we then convert it into Json so that in the end we return all of this into the use Query now what can we do well we can First grab the data directly from here and you saw that there were some autocomplete because there's actually a lot of things you can get from the use Query and you should look at the documentation to see all the use cases I'm going to show you guys some of the most important ones so we can grab the data right and the data specifically um I'm going to show you guys over here how this data looks like as you can see it looks like this it has a user ID an ID a title and a completed right because because it's a to-do task and it is an array so what we want to do is we want to come over here and we want to Loop through this data because the data will have will be a an actual array like we just saw so I'm going to Loop through it by saying data. map we're going to get the to-do info from here so to-do and we're just going to return a div with a couple pieces of information right we can more specifically just pass in uh both of the to do. ID just to take a look at it so I'll say um H1 and I'll pass in the to-do ID so ID equal to this and let's also try to get the title so title too. tile and you can already see from the background that it is actually working right we're getting both of them oh did I write it wrong did I write it with uh yeah title but yeah we're getting everything directly and it's everything is bolded and massive wait I'll just zoom out actually but yeah we're getting all of the data so that's the most basic thing we can do but we can also do a lot more we can get the state of possible errors like this and what would you want to do if you have an error well you might want to check first to see if there's any errors and then return um maybe like a div with an error message something like there was an error now if any error occurs this is what is going to be displayed um there is also another one which is the state of loading so you can get a is loading it's a bon so you can actually come over here and say if is loading then return I don't know a spinner or something saying like data is loading something like this you you guys will'll see that every time I refresh the page now for a brief second it shows data is loading over here obviously you can make it look better however you want but it was really simple we didn't have to create all the different states everything is handled over here and in its core this is the most basic thing that react query can do now I want to show you guys how to do the other part of data fetching which is actually altering data through what is known as a mutation so there is a hook for mutating data called called the use mutation hook I'm going to bring it over here as well and in order to test uh the use mutation hook we're actually going to be using a different set of data from the same API it's actually data related to like posts and the reason why we're going to do that is because um this is the only one that they allow me to also make post requests which is something we're going to be doing with the mutation but um yeah that's basically it I'm just going to replace this with posts and since it kind of looks the same it doesn't think I don't think it would change that much uh the the two St things are pretty similar but yeah the the only difference is that it also includes a body so I'm actually going to change this to like an H I don't know four and I'll put a body as well like a P tag with um to-do do body just like this and we can see over here that this is how the posts look now with this we can actually make add posts to this thing so what I want to do is I technically just want to have a button because since this is not I'm not building the website for for like completely uh we're going to be faking the data obviously so the button over here is um I want to add a post so we're not going to actually get user inputs through creating inputs we're just going to hardcode the data into the request so what we can do is we can grab the use mutation hook over here and I actually go below the usequery and we can open close and say use mutation just like this now similar to the use Query we're going to open up this and instead of putting a mutation key for now uh we're going to put a mutation function and here what I want to do is I want to uh basically say that whenever we call this function we need to pass in some arguments to it why is that well because when we going to when we fetch the data uh we don't need any arguments unless we're patching by ID or something like that with mutating we specifically need to add some data and send it through the body so I'm going to grab over here the new post we're going to add and whenever we call this mutation it's going to use that we have to pass this as the argument to a function and as the opposite over here what I'm going to do is I'm going to just say fetch then pass in the same URL and I'm going to specify uh the method of which we're we're going to be making this request the method will be um the post right so I'm going to say method and then post like this and then we need to pass in the body and the body will be basically a json. stringify version of um so say stringify of the new post we're going to be passing as an argument right this is going to be an object containing all of the data and then uh we want to just say dot then grab the response again and say res. Json just like we did before we're going to save this and um hopefully it works now what do we get back from this used mutation well we get back first of all a function called the mutate function right and this is the function we're going to call with our new post data so over here on the ad post I want to say onclick whenever there's a click we want to mutate and we'll pass in over here an object containing the data so since the data of a body of a post is like this I'm just going to copy this over here and paste it here um and here it is we can fake some data I'm going to say that the user ID of this is I don't know 5,000 just so it doesn't uh interfere um and the ID is 4,000 the title of this post will be hey my name is Pedro and this is my channel uh just so we can differentiate them and then the body is um this is the body of this post I don't know something like that then I'm going to save this and let's check to see if it works but before we check we're going to get some information about the mutation just in case it fails I can also demonstrate to you guys um how exactly um to handle those errors so with the mutation uh you can also get some uh information about if the mutation is loading and if there was an error if it was success anything so one thing we can do is we can grab the is pending which is similar to the is loading we can also get the is error and also the is Success so what I can do is I can technically come over here and say that if there was any errors uh similar to this one I'm going to say if there was error or there was um an is error from the mutation then we want to say that there was an error uh similar to this we're going to say the data is pending um actually I'm not going to do anything with the data is pending other than maybe just say like I don't know uh if is pending actually I'll put it up here I'll say if is pending I just want to see something right at the top saying um maybe a text saying data is being added something like this and then I'll put a I'll wrap this around with curly braces and just say um is pending is true if that's true then I want to show this so that's all we can do for now I can also use the is success but it isn't that important for now but let's test to see if this works I'm going to open up the network tab so we can take a look to see if the post requests are actually done because one thing um is that this specific API although I'm going to be adding something and making a post request the data isn't actually added to this list over here we're going to have to addit to the cache which is part of the tutorial later on but it does give us a successful request right so this is the query one that we made now let's click on ADD post and we should see that there was a correct request as well as you can see it says it was created this is the data that we sent in the request which correlates to what we did and it seems like the response was uh an ID for it and I guess since it was a successful one it means it was created now if we actually want to see the correct data being dis displayed here like with everything that we added um maybe I think we just have to add some headers to this like I can come over here and add headers and then just say that the content type is equal to probably application SL Json uh Chet uh UTF 8 uh maybe just adding this will actually make it work uh why is it oh I have to do this um let's see let's see if we get back the whole request oh yeah that worked so we got back over here the data that we sent and it was a successful request so this is how mutations work and that's again the second big part of what react query does but now it's when we get into the cool stuff which is all the caching stuff all the all the individual functions and and variables that we can get related to our data that you have no idea about um this is where we're going to be talking about it so in order to go ahead from the tutorial I just need to give you a very brief explanation of what the cache is so whenever you have uh a website there is obviously data that is stored in databases and such but there's also readily accessible and quick data uh inside probably inside of your memory um related to uh things that is happening in your website now when we're using requery they have their own cash management system and they store all the data from the queries that we make in our application inside of there and we can instead of fetching again for data we can sometimes just use the data from the the the cache that will save us uh costs in making requests to an API um and it will just keep using the data that is in the cache and and if we need to update that data we can either do it manually or have some sort of automation for it so what I want to introduce you guys is to the idea of invalidating query it's very simple um basically instead of U manually altering our cache we can Mark queries as stale and potentially refetch them now in this case specifically it will refetch the data and I'll show you guys exactly what it does so in the used mutation hook we can actually get something else over here at the bottom below the mutation function called an on success so there's an on error an on mutate an unsettled and an on success obviously the on error is a function that you might call if there was an error the on mutate is if the data was mutated or if there was basically called um the unsettled I'm honestly never not sure I've never seen it probably when the whole thing is is done that's what it means probably and on success is obviously a function that you can call uh whenever the mutation was successful and I want to basically say that whenever this uh specific mutation is done I want to grab the query client that we don't have access here we only have access in the index.js uh but I'll show you guys how to get it we have it over here where we created it but we're going to say query client dot uh query client. invalidate queries just like this uh this whenever we put we call this it will basically uh tell whatever query we inv validate over here to refetch its data so let's first get the query client which we don't have to do that it's actually not that hard there's a hook for getting the query client so use Query client and we can directly just uh get it from I don't know up here I just say um const query client uh no I keep pressing the L but yeah query client is equal to use Query client now we can use this over here at the bottom and in order to invalidate a query we have to specify which query we want to invalidate and that's where the query keys that I mentioned before come into place we can pass over here that we want in invalidate all the queries with the query key equal to um uh posts which by the way I didn't change when I changed the API we we're working on uh but we have to put posts now it's given us an error because it's saying query client is not defined because I need to change this to uh lowercase Q to match the variable but yeah so what we're telling here is to refetch the post data when the mutation is successful because then if we are actually using a website with a real API where you can add data to it we would want to maybe fetch the data again um to see the new result appearing so we we can test this out I'm going to open the network tab you guys will see that so far there's only one query right uh but now I'm going to click at posts and you'll see that now two queries happen uh two fetch requests one is to mutate the data and it is returned and the second one is to refetch the data in order for us to have it uh updated right now that isn't specifically related to the cache especially because in this API we're working on it doesn't matter what kind of data we add it's never going to be added here because uh they don't allow me to add it's all fake but we we know the mutation is working because the request responded with a 2011 which means it was successful but although this is really cool um it does refresh the data right so there's ways for us to actually manually edit the data in the cache and display that data inside of our website right uh so instead of refetch the data what we're going to do is we're going to come over here and we're not going to tell query client to invalidate this query and we're going to tell the query client to set the query data equal to and then over here we have to pass in two things the first thing is we need to pass in uh a list or the list of query keys that we want to actually edit the cache with so I'm going to do posts over here because this is the query that we want to edit right and then what we get over here is a function and this callback function is similar to how when you have a reduce or a filter or any of those uh primitive JavaScript functions that you can use um you basically get some data related to uh how the state of this is right now and we can call this OD posts and you have to return the state of it after so you can't mutate the data directly you have to return how this data is going to look after the changes are done so if we think about it um the post post query returns a list of posts so we can get the old posts from here and we can also get the return from this uh request directly from this and we know from uh the video so far that we'll get in uh like just the post that we try edit uh adding directly so we get it through new post um and we can just return um the old posts so all of the old posts before plus the new post that we're adding and you can see that now instead of uh just having a like fetching the data you'll see that I'll inspect element over here I'll go to the network Tab and I'll refresh the page we'll have the first query right but then we're going to click on ADD post and we only have one which is fine because we're not invalidating the query but the difference here is that we manually edited the cache of that query so that means that now if we go down there we should see an extra item with information that we created and that's exactly what we see now if we were to refresh this you should see that as I go downstairs the thing is not there anymore because technically we didn't edit the data that was uh created right we didn't make a change in the database we just edited the cache that is in our current memory now as we start working with cache we have to understand um things related to um the state of the data you're fetching and there's a lot to be said about that so we want the whole purpose of the cash is we want to have stuff being up being the most up to date possible but also minimizing the amount of requests we make but at the same time that is not always possible because what we're doing here uh by editing directly the cache is fine but in a lot of cases doing this optimistically is not a good idea sometimes making that extra a refetch is important in order to maintain accuracy with the data so we can do a lot of things in react query to make sure that we are constantly up to date with that data and one of the things that I think is the most useful is determining the stale time of a request so what exactly is the stale time and how does it differ from uh something like the cash time which is a concept that I will introduce as well well the stale time if I come over here to uh our use Query there's a lot more that we can actually add to this uh query so we obviously added the query function but we can also add the still time over here the still time is in milliseconds the length of the time you are accepting this query to be as it is so if we have something that some sort of data that is constantly changing or that even changes after I don't know 60 seconds and we want to just check to see if the data is up to date well we can add a certain number over here for example let's use that 60c example for this 60 seconds in milliseconds is 60 with three zeros at the end right this is around 60 seconds so what this will do is it will actually when if there's no changes in this query in 60 seconds it will refetch the data automatically now for the purposes of this example I actually decrease this to uh 6 seconds because like I'm not I'm not going to wait for 60 seconds just to show this to you guys actually I can make it shorter I'll make 4 seconds something like that but this isn't actually enough to make this refetch and I'll explain to you why um when we set a stale time I know I said it would refetch automatically but with only one condition which is um becoming stale making a query become stale doesn't necessarily mean it will request again but there are certain actions that will make it request again so stale queries are refreshed automatically in the background when when the following things happen first of all when a new instance of the query is mounted or when the window is refocused when the network is reconnected and when the query is like optionally configured such that it has a refetch interval which is something I'm going to show you guys um specifically an example we can test here is uh switching tabs or because when we switch tabs um we are refocusing on the window and you can see that after 3 seconds the new thing was fetched and I can try again and again but it won't because it hasn't been 3 seconds now it has been so we can come back you see what I mean right um this is one of the actions that can make this happen but if you also want to add a ref refetch interval instead of a still time that will actually make uh that initial behavior that I said which is every 4 seconds um it will refetch the data so let's let's try this out uh I refresh this we have here the posts we wa 4 seconds and it fetches again wait 4 seconds and it will fetch again so this is really great for a kind of data that isn't exactly um specific uh I don't know you can use it for like every 1 second if you want to do that but you can also use it for refretting every 10 minutes you know something like that if you have that kind of data now you can also set up a a default stale time um for all queries if you're interested in that and the way you do that is you go to actually where we defined our query client and now you can actually add some default options to here which is something that applies to every query or every mutation to specify the default options for the queries we just say queries like this and we can add a TA time here such as uh I don't know 6,000 or actually I'll put 60,000 which is 60 seconds and this will apply to every single one of them now if you recall when I was explaining St time I mentioned that there's another concept which you might get confused with because it's very similar to still time and a lot of people do get confused between the two um and it it's actually a concept that changed its name uh which C which causes even more confusions which is the idea of the cach time or the garbage collection time so previously um you could set something for example over here um like this you could say cache time and set interval to 6,000 now instead of calling it Cash Time you put GC time which means garbage collection time which honestly makes more sense and that's the previous name caused most of the confusion because what this is is uh if I were to set this query to have a garbage collection time of 6,000 so basically whenever the query is unmounted and it's not longer being used um since there are no more active instances of this query uh the time you put over here will be kind of a timeout set for when react query will delete and garbage collect the query so it's just a way for us to not keep unnecessary data in our cache so what I would recommend is first of all not setting this individually for each query but again setting it over here as a default option and setting the garbage collection time to around double from what you have as your St time if you have anything over here um by default it's 5 minutes but I'm going going to put 10 minutes uh the way I'm going to do that is I'm actually going to put 10 um then we need to multiply this the amount of minutes times how 60 seconds which we all know it's it's 6,000 or 60 * 1,000 uh and this becomes 10 minutes um this is I recommend putting the garbage collection time as more than the still time uh that's just how I think it works better U maybe you can also just use the default option initially but uh obviously adapt to whatever case you need now there's some other things I wanted to touch upon uh the idea of parallel queries is something that I haven't said but it's implied I believe you can have multiple queries at the same time imagine this is quering something else uh it has a different ID uh you can make all of them at the same time and just use different variables um there's also uh dependent queries as opposed to parallel queries which basically are two queries that depend on each other I don't have the API uh I don't have examples I can use with the API but let's imagine something like this uh this query is querying uh data right I'm going to delete all of this now imagine that this over here is getting I don't know one post specifically right it's just getting information about a post and this over here would include data about that post like a data. ID right and this query over here needed that ID in order to fetch information about something right so I could get the ID from this data like this saying data. ID directly like this and then I can actually add a thing over here called enabled and this enabled uh option over here basically says that this query will only execute as long as whatever Boolean operation you put over here is true so whenever the ID is not null and also true we put two exclamation points to make this convert this into a a Boolean then this will execute so basically if you have a query that depends on the other just make the first query first get the data and add that data as part of the enabled because then whenever you get that data this query will execute so that's kind of the idea of dependent queries now one cool thing you can also do is um the idea of a refetch on window Focus right we already have that set as true by default uh you remember if we set the stale time right as like I don't know 3 seconds and we were to uh wait 3 seconds and keeps like switch after 3 seconds and the thing becomes stale it will refetch right but we can remove uh focusing on on the window as a possibility to cause that refetch by coming over here and saying refetch on window Focus equals to false so I can come over here and now even if it passes 4 seconds which is the taale time it won't activate the post as you can see it is not refetch because we set that as not a possibility now let's imagine you want to I don't know like this ER query is prom for erroring but you really want to keep trying to make it work you can actually put a retry option over here the retry option is basically you put over here a number and it will try this amount of times to make this request before it accepts failure so if we were to test this I can make this query definitely fail refresh this page and you'll see it failed but it will keep trying for five times until it gives up see one more time uh let taking bit and yeah just the last one until it still data is loading right but it keeps trying uh I don't know how long yeah the last one definitely failed so there will be no more attempts so this is uh a really cool thing especially if you're working with things with with data that may require uh a retry not always you'll have it first try right not always there stuff can happen but maybe putting the retries to two or three might make sense in your use case now the last thing I want to talk about um and again if you guys want more things about react query than I've put on this video I can definitely make one thinking of making a video on teaching you guys how to paginate and use the use infinite query hook that allows you to to basically fetch data by scrolling down on your page and stuff like that I'm thinking of making a video for that but if you guys want to see more about rqu I can definitely do that however the last thing I want to talk to you guys in this video is just give you guys some advice on possible bugs the main bug I see people uh dealing with is oh why is my cash not working well maybe it is not working because you didn't create your index.js your query client outside of your components so if I were to come over here grab this and put it inside of this what do you think would happen obviously it's failing right now because this I need to play around with it but you get the the gist right if I were to pull this here and do this why would this not work well because the query client is what holds everything related to our applications react query instance right including the cache so if we were to put it inside of the app every every time this app component rerenders we will create a new query client which means that um every times the app component renders we would create a new cach storage thus making all of the cach changes we've currently have be useless so definitely make sure you put this over here and not over here now um there's a lot more to this um I would recommend if you're for Best Practices purposes I recommend instead of making your query functions like this Direct like this I recommend creating it outside or in a different file maybe something like get posts and then making the function something like this and then directly putting it um over here uh where is it putting it like over here and I recommend doing this because um I feel like it gets more organized then you just you don't have a bunch of functions just randomly inside of your component you can separate this into a different file makes it look a lot better and um um in situations like this one where the mutation is a big thing because you have to include the body the headers everything it looks even better if you were to grab all of this and just put it somewhere else right so yeah that's that's pretty much it if you guys enjoyed this video please leave a like down below if you want to see more um I'm going to post this code and put it in the description just if in case you want to play around with it but I would recommend just doing it on your own um I appreciate you guys watching this video If you enjoyed it leave a like as I said I'm really grateful that I'm back making videos I'm excited first week I'm posting two videos um in a long time so really hyy for that and stay tuned because a lot more is coming so yeah that's basically it hope you guys enjoyed it and I see you guys next time
Info
Channel: PedroTech
Views: 10,849
Rating: undefined out of 5
Keywords: computer science, crud, javascript, learn reactjs, mysql, nodejs, programming, react tutorial, reactjs, reactjs beginner, reactjs tutorial, typescript, react js crash course, react js, node js, express js, pedrotech, traversy media, traversymedia, clever programmer, tech with tim, freecodecamp, deved, pedro tech, react query, tanstack, react fetch, fetch, react fetching api, react query data, reactquery, react-query, useQuery, useMutation, react query caching
Id: NOvx4LB6Hfk
Channel Id: undefined
Length: 39min 57sec (2397 seconds)
Published: Wed Feb 28 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.