Learn React Query In 50 Minutes

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
as you can see I've been busy taking notes on react query which is one of my favorite react libraries and in this video I'm going to cover everything you need to know about react query and by the time you're done watching this video I guarantee you you're going to love it so much you're never going to want to go back to the old way of doing fetch request [Music] welcome back to web dev simplified my name is Kyle and my job is to simplify the web for you so you can start building your dream project sooner and in this video I'm talking all about tan stack query which you also may have heard referred to as react query now if you want an overview of exactly what this library is and what it can do for you in depth I have a video that covers exactly that it's great to watch before this video so you can get an idea if watching this long video is actually worth your time in it something you're going to want to use but a quick overview of what tan stack query does is an asynchronous State Management Library the key behind that is it makes managing asynchronous State most likely State coming from an API like when you do a fetch request or an axios Quest it makes dealing with that state incredibly easy because it handles caching really well handles pre-fetching it handles all the updates and getting data from your server it just makes all that seamless and easy and it does almost all the hard work behind the scenes for you if we scroll down a little ways here you can see all these different things that tan stack query is doing for you and we're going to be covering pretty much all of these in this video now to get started the very first thing I want to do is show you how to get started with 10 equity in a react application and how you can build out a very basic shell using the most basic features so the first thing you're going to need is some type of react application I created a simple Veet app deleted everything and just has one single H1 so it's super straightforward now to use this you just need to type in npmi and you want to type in at tan stack slash react Dash query and this is going to install the react specific react query library now if you wanted to use view or stealth you would need to install the spell specific version now the next thing we can do is just add on to that that we want to install the dev tools as well so it's react query Dev tools these are tools that are built into react query that just make development a little bit easier and allow you to really see how things are working behind the scenes which is going to be great for this tutorial video now let's just get our application started here there we go so that way it'll be rendering over here and you can see if I make a change it'll change on the right hand side of the screen that is perfect now the very first thing you need to do to get started with tan stack query is you need to create a provider that wraps pretty much your entire application or at least everywhere that you plan to use react query which let's be honest is probably your entire application so we can come in here and we can do a simple import and we want to import the query client and the query client provider we want to get those from that at tan stack react query library that we just installed so this provider is just going to wrap your entire application so I like to just put it inside my app like this and put my app right there so this wraps your entire application and this query client is the actual client that you're going to create and we can just do that right here so we can say const query client equals new whoops query client just like that and inside of here you could pass some default values to your query client but for now we're going to leave everything exactly as is stock so now what we can do is we can just pass in our client here which is our query client and if we save you can see our application is working just like before but now our entire application has access to this query client so we can do all of the different things with react query so now with that done I actually want to show you kind of the basic overview of all the different major features you can do with react query and then after that we're going to dive into each individual feature really going over exactly what's happening I just want to do it this way so you can really see what you can do with react query and why it's so amazing so the very first thing I want to do is I want to create a really simple function called weight this is just going to allow us to simulate some artificial load times I could manually slow down my network speed but this is just easier to do in my opinion and allows me to really fine tune what I'm showing you so now the main two things that you can do in react query is you can do a query and you can do a mutation a query is just getting data from somewhere and then a mutation is changing some type of data so for example if you want to get a list of post that would be a query and if you wanted to create a brand new post that would be a mutation those would be really the only two things that you can do with react query so it's pretty easy to get your head around what's going on there so for now I'm just going to hard code our post data so I'm just going to say const post equals an array of two different posts super straightforward and then what I want to do is I want to import what we're going to do we're going to use Query we're going to use mutation so these are two custom hooks that come from that react query library and they allow us to get data and change data so let's first take a look at a used query so if we come in here and we call use Query use Query takes in an object and as you can see if we come in here there's a lot of different things we can specify on this object but there's really only two things that you need to worry about we have a query key and this is going to be a key that uniquely identifies this query in our case we want to get all of the posts so we're going to pass this an array that the first value is post this always takes an array in our case we're just getting post so we're passing it the label of post like I said I'm going to talk more about exactly what all this does later but the main thing to note is this is just a unique identifier for your query you could make it have multiple things in the array it just needs to be unique the next thing that we're going to need to do is we're going to need to give it a query function this is the thing that is going to run to actually query our data so in our case our query function here we just want to return a promise this always accepts a promise so it's any asynchronous code that's why it takes a promise so let's pass it a function here we can use that weight keyword so I can say weight 1000 that's going to wait one total second and then after that one second has elapsed I just want to return all of our different posts in a brand new array so we're just going to be getting all of our posts after a one second delay that's all that this is going to be doing and then this is going to return to us a bunch of different information I'm just going to call this my post query if I can spell properly just like that if we come down here and I say post query dot you can see I have a ton of different information related to what's inside my post query but some of the main ones you see is like data error success loading and so on so if we just give this a quick save here you'll notice everything appears to be working we're not getting any errors which is really great so let's go ahead and actually implement this post query first I want to have a couple if statements so if my post query dot is loading well that means that I'm currently in the loading state so what I'm going to do is I'm just going to return in H1 that says loading just like that and now if I save and I refresh over here you can see we get that loading text for one second then my poster returned so we're no longer in the loading State let's do the same thing for if we have an error if we have an error I'm just going to return here a pre-tag this pre-tag is going to Json dot stringify my error so we could say post query dot error to get the actual error itself so this is going to be like your generic error message or whatever is returned I'm going to put this on another line so it's a little bit easier to read there we go so now if for some reason this returns an error so what we can do is we can just make this reject a promise so we can say promise dot reject error message now if we give that a quick save every refresh over here we're going to load for a while and it's loading it's loading and loading and eventually it's going to return to us our error message now you will notice the loading is taking much longer and that's because it constantly retries over and over and over again to make sure your function fails multiple times so it'll do multiple retries of your query function and it'll wait between each retry until it fails multiple times in a row and then it'll return to your error your error and that's why you saw that loading took much longer because it was trying it and then it waited and then it tried again and then it waited and then I tried again and it failed the third time so it showed me the error message that's a really useful feature to have those automatic retries built into the system now let's obviously bring that back so we are returning our post just like this so now after one second it'll be finished loading and now we want to show some information related to our post so I'm just going to put a div here and inside here what I want to do is I want to Loop through my post query.data this is going to be all the different data and the important thing to note is that if we're not in the loading State and we're not in the error State well that means by default we are successful which means our data will already be populated for us so we can just map over this data for each one of our posts and for each one of our posts what I want to do is I want to return an element for our post so let me just get my spacing everything set up here so we're going to create a div which has a key which is going to be our post dot ID and we're going to have inside of that a value which is our post dot title I believe is what we called it yeah post dot title there we go close off that div and now if we save you can see it says loading and now it's showing both of our different post post one and post 2 just like what we have up here so that's really basically how you do a query essentially you just give it a unique identifier you give it a function to get your data usually this is going to be some type of fetch or axios request then you can check for all your different statuses and then finally you can show your data down here and the next thing I want to talk about is how exactly you do a mutation so we have used mutation here it works very similar to use Query so we can say that we want to have a create new post so we're going to say new post mutation I'm going to set that equal to use mutation and this again takes some objects but you only need to pass one thing specifically here and that is mutation function just like you have a query function you have a mutation function and again it expects to return a promise so inside here what we want to do is we want to First weight 1000 that's again just going to simulate what would happen if we actually did have a network request because right now everything is instantaneous and then what I want to do is I just want to create a brand new post so I'm just going to copy down this code for exactly what's Happening Here and I'll explain it in just a second here and I want to make sure we pass a title in just like this so what we're doing in this dot then is I'm just taking my post array I'm pushing a brand new value inside of that which has a randomly generated ID as well as a title which is being passed into our function now the key here about the mutation function is it can take in whatever data you want it just takes in one single property in our case it's a single title and it's going to be placed right here but we can make this whatever we want it to be it's just the singular thing that gets passed to our mutation function it's always going to be one single value then what we can do is we can actually use that mutation at a later point so we have all the same is loading is error and so on properties and data and such but the key is we also have a mutate function that we can call on this let me show you exactly what I'm talking about let's create a brand new button and this button is just going to have the text of add new there we go and when we click on this button what I want to do is I want to add a brand new thing here so to do that what we can do is we can say we have our new post mutation and we can call the mutate function and this mutate function is going to take in whatever value we want to pass in in our case it's a title I'm just going to say new post whatever we're not going to make it Dynamic it's just going to be a static new post value and now when I save and I click add new it's adding a new post but you'll notice nothing is actually happening it's not showing up on my screen you will be able to see if I just do a quick quick console.log of our post array here you will see that it does show up so if I just do this refresh my page give it a second load click add new you can see right here it's showing up we have that brand new value that has the new post showing up inside here but it's not showing up on our actual post list and the reason for that is because of the way that caching and everything works inside of react query to make this a little bit easier to understand what I want to do is just refresh this real quick we'll go back over to our main page here and I actually want to show my Dev tools so we can do is we can come in here with another import and this one is going to be from that Dev tools version and I just want to import our Dev tools and we're just going to add this as a single component into our page just like that now if I click save you'll notice if I move my camera out of the way that we have a bunch of Dev tools showing up on the very bottom of our screen and these Dev tools essentially allow us to see exactly what's happening with all of the different fetch requests and queries and mutations and everything on our entire page so you can see we have this post request here I'm just going to expand my page and move my camera even further out of the way let's just get rid of it there we go so with our post if we click on this you can see we have a bunch of different details you can see what my query you know key is right here you can see all the different data being returned to it you can see that it is currently in a stale State and we can like refresh it and validate so if I click refetch it's going to refetch that data for us if I invalidate it's going to make it stale which will force it to be refreshed on our page I can remove it and so on so I can do everything I want inside of here but the big thing is I can really see what status everything is in and you can see currently this is in some stale status now let's go ahead and close out of that and get our code back to where we had it before I'll bring my camera back and I'll put it back in the corner for us now understanding how all this data is cached helps a little bit because now we know why our data isn't being refetched automatically for us and that's because we have this query key of post right here and it queried out all the information for our post showed it on our page and it was like okay we are good to go this mutation is changing our underlying data for this query key right here so what we really need to do is we need to set up an on success and this on success is saying whenever we have some successful data what do you want to do and in our case I want to just invalidate the query that we have here and to do that we need to use the use Query client hook to actually get our query client so we can say const query client equals use Query client and this is essentially just going to return the thing that we created right here that's all that's going to do but it does have some nice functions on it so we can say dot invalidate queries and what we want to do is we want to invalidate the posts query so whenever we have a successful mutation where we add a new post I want to invalidate my old post so now if I click add new and I wait for all of my different weights to go through you can see it refetch that data immediately for us if we go ahead here and we come in and we make sure that we disable this button whenever we're voting so we can say new postmutation DOT dot is loading it's going to be disabled so now if I click add new you can see it is currently disabled and now it finished adding the new and now it's refetching in the background to get that actual new thing we just do a refresh right here and I can actually show you right here if I move my camera out of the way again exactly what's happening in the background so I click on add new you can see it's now refetching all of the information from my post and that is how I get the new post so every time I click add new it's going back and refetching all that different data for us and showing up that new Post in the list now I know all this may seem a little bit complicated but this is kind of an overarching view of exactly what you can do with react query you can see that you can make queries you can make mutations and you can actually modify an underlying cache of how everything works behind the scenes and the next thing I want to talk about is specifically everything to do with use Query that'll make a lot of what we've gone through understandable a little bit more and I'm going to go really through the nitty-gritty of all the different possible things you can do with the use Query hook now the very first thing I want to talk about when talking about this use Query hook we can just get rid of all the stuff from mutations because we don't need any of that right now there's the thing that we want to understand is how it is exactly this query key works that's one of the most important parts of the entirety of this use Query hook the key about this key is that it must be unique for the actual query you're making so in our case we're creating all the posts which is why we called this post what happens if we were getting one individual post like let's take a look at some URLs let's say we wanted to get the URL slash posts we wanted to get the URL slash post slash one to get an individual URL let's say that we wanted to filter our post by author ID where author ID is equal to one and let's say we wanted to also get all of the posts that have a specific comment so we'll say all the comments for that specific post how exactly would we write query keys for all of these well the thing that I like to do in my opinion is I like to break apart my URL every time I have a slash I like to think about that as a new element inside my array array and then I just pass the value into it so this one right here would look like this where we just have our post pretty straightforward that's exactly what we've done here this next one here I would have that same slash post at the beginning but I would also put in my ID of one here so like you may have something that's like post dot ID that you'd put inside of the array just like this for this next one it's going to be pretty similar but whenever I have filtering that I do like this I like to put it inside of an object so I would say like author ID is one or you know whatever it is so we'll just say like one like that that's going to be the filter that I use for this one and then finally this very last one is going to be very similar to what we did up here with our post ID but I'm also going to put my comments on the end of it so this is kind of like the style that I like to use the main thing that you want to realize is whenever you pass data like a post ID or an author ID into your query key here you want to make sure that whatever function you define actually uses that data that way you can make sure that your actual key and the thing that you're querying and your function they're synced up together and that way when you need to do some type of invalidation you're invalidating all the queries that have that particular key now our query function here that's something we've already talked about the key is that it must always return a promise because this is going to be for asynchronous data and it actually does take in a parameter inside of it so what I can do is I can just print out that value we can just say object and then in this dot then here I can just print out that object so you can see exactly what's being returned here console.log object there we go and I make sure that this is a return and now if we just inspect our page go over to the console make sure that I do a refresh here there we go you can see that it's returned to us a bunch of information we have a meta we have a page param we have a signal none of those are important at all the real key here is that we have our query key so if for some reason you needed to access whatever you pass into your query key you can do that right here by just saying query key just like that this is something that you'll use fairly often I would say so it's important to know that it exists the other important thing to note is if you have any errors that are thrown inside of here or if you reject a promise those are all going to show up in the error object down here for your actual query and if you're using something like fetch that doesn't actually throw errors by default that's something you want to make note of and actually throw those errors but generally you're probably going to use something like axios instead of Fetch and in that case you don't have anything to worry about and then lastly I kind of want to talk about some important properties here so if we say post query dot you can see we have our data which is really important we have our error property which is also important we have a bunch of statuses so is error we have is loading we have is Success those are all really useful and then we also just straight up have a status property which we can compare to error loading or success so we essentially have ways to check all of our different states which are really useful as well as get the data or error based on what state we're in now one of the last used query specific things that I want to talk about is actually how all of the state management for stale fetching invalidated and so on work in order to understand that I actually need to change my code a bit so I'm going to modify the code and then bring you back here okay so here we go I have quite a lot of changes made to the code but they're going to be fairly straightforward changes essentially we have two different lists that we can show and these lists render almost exactly the same code like if we look at post list one you can see it's very similar to everything we've talked about so far it's rendering out our loading and our error State and it's showing my post down here super straightforward stuff that's going on but list two it is literally the exact same code I just changed the number here to two so choosing the exact same query key which is the important thing these two things they use the exact same query key but they're on different pages and they cause an entire app refresh so these are the same query key but they're in two different locations in our application that's really important to how this is working then I just have this get post function which is just querying a simple API for us and returning this to a list of all of our different posts pretty straightforward stuff that's going on and as you can see when I change between these Pages my list is showing up just fine now if I wanted I could slow down my network speed all I need to do is just change my throttling here to like a slow 3G and now when I swap between these Pages if I just give my page a refresh first so it's going to refresh my entire page that'll take a little while and now when I swap between Pages you'll see the loading State and so on so if I give this a second to actually load up real quick it takes quite a while working on that slow 3G throttling connection but once it loads you'll see that it'll say the text loading because that's what we're rendering right here and then once it's done loading it'll show post list one because that is the default page that I'm rendering right here there you go you can see it just popped up it said loading and then it actually loaded if we look here you can see that our post query is currently in the stale State now when I go to my list number two and I click on that you're going to notice my data is here it's populated just fine but I was in the fetching state for a while before it went back to stale and that's because react query is smart enough to refetch your data in the background essentially what that means is when you swap between different pages or any time that you need to refetch your data so if you remount a hook so in our case here we swap Pages which means we're doing this use Query hook for the first time so it's being mounted so it's saying hey is this data stale in our case yeah yes it is stale so what you should do is refetch that data and then once the data is refetched it's going to show us the brand new data on our page also if I unfocus my page and refocus that's going to cause it to refetch again or if for some reason my page lost internet connection and then reconnected obviously it'll do some refetches in that case now the important thing about this though is I have my post here cached everything at this query Kia slash post is cached and stored in memory so when I spot Pages it can show me the cached version of that page while it refetches in the background and then shows me the new data once it's actually finished fetching this is really neat really powerful and something that's an absolute pain to write out on your own you can actually see all this fetch information if I just come in here post query.fetch status you can see that that is going to be equal to fetching idle or paused and the way that this fetch status works is anytime that you are refetching your query it is going to be in that fetching status if you are currently not doing anything so for example you're not fetching It's Already Done it'll be in the idle status or for some reason like you lose connectivity to your internet it'll be in the pause status if it was in the process of fetching and then for some reason was not able to finish so to understand the entirety of how the fetch status and the actual just normal status work together is when your component very first mounts what's going to happen is your fetch status is going to be in that fetching State and your status is going to be in the loading State because the first time you load the page it's going to fetch the data and it's going to load the data this is the very first time that anything with this query key is loaded then if your data comes back successful this is going to change to success and this will change to idle well if it's an error this will change to error and the data or error property will be set accordingly depending on if you have an error or success now if you go ahead and you load a new page that uses this query key and you already had a success for example the status will stay success but your fetch status will change to fetching because now it's refetching the information in the background once it's done fetching this will change back to idle and it'll update your data as as well as your status depending on what actually happened now you probably did notice an interesting fact though as soon as we fetched data it immediately goes to stale instead of staying fresh and that's the default Behavior if you don't want that behavior what you can do is you can actually change how your stale timer is set up so in our case we can change it as a default by coming into here all we need to do is we need to change our default options we want to change our default options for whenever we're doing a query and we want to change the stale time and this is going to be in milliseconds so if I just do a thousand times 60 times 5 what that's going to essentially do is tell us that we don't want our data to go stale until it's been in our cache for over five minutes so now if we just give this a quick refresh here it's got to refresh everything I'm just going to inspect my page and turn off all my throttling so it can go back to normal speed now you can see that our data is currently fresh and when I change Pages you'll notice it never actually goes to this fetching state it stays in the fresh State until it actually becomes stale and that means it has not been fetched for however along my stale timer is set to which we can set here or if we want we can set it specifically on an individual query for example if I wanted this one to go stale after one second I would do it just like that now the final important thing to understand about fetching is you can actually manually cause something to refetch on its own so let's put this back to exactly what we had before and let's say I wanted to refetch some data every so often what I could do is I could set a refetch interval and just give it a time so let's say every one second I want to refetch my data so if I'm on post list one it should refresh every single second and you'll notice it briefly flashes over to fetching every single second and it's getting that data and over and over and over again every second it's refetching that data for me now the final basic feature of use Query I want to talk about actually requires me to change my code yet again so if we look back at our app we have a brand new button here for going to our very first post so the post of the ID of one and if we look at that post function here you can see that we have a post query which is getting a single post from a git post function which is stored inside of our API super straightforward you'll notice our query key now contains the that ID which is really important so this is separate from our original post and you can see here we have a user query which is commented out for now we have some data about our post super simple loading status we have our title showing up our body and then we're trying to render some information about our user the reason we're doing this is because by default our post doesn't have the user's name it just has the actual name or it has the ID of the user so what we can do is we can print out host.user ID just like that I think that's what it's called yeah user ID so if I do Post query.data dot user ID and I save go to my first post you can see we are trying to get the user with the ID of one I want to get the name of that user which requires me to query my API but the problem is is I only want to run this user query after my post query has finished because otherwise I don't have a user ID to reference that is where the enabled key comes in so what we can do is we can say enabled and we can either set this to false or true or an expression that evaluates to false or true so what I can just do here is I can say that I only want the this to be enabled when this is not equal to null so whenever I have a user ID then I actually want to be able to run this function otherwise don't run this at all and now if I just comment out the rest of this code you can see this is going to work fine if I save you can now see if I get rid of that user ID it's showing the actual name of the user so it's first making this query and then it's making this query and we can actually see that if I just slow down my page so if I go to inspect change my network tab here to be a slow 3G again just like that and actually let's make it no throttling refresh our page then we'll go slow I click over here you can see we're loading our entire post now it's loaded so now we're loading our user information and now that user information is loaded so it's doing one after the other in order I really love this enabled key because it makes sure that you only render queries when you want them so if one query depends on another query you can really easily do that with enabled or if you just want to disable query for some reason you can do that as well now that covers everything you need to know about use Query at least the basics so the next thing I want to talk about is use mutation which luckily there's a lot less that we need to cover so again I've modified our code a little bit if we go to our app here you can see I've added a button for going to creating a new post when I click on this you can see we get a page that accepts a title and a body and we click the create button to actually create a brand new post for us if we go to this create post page it's pretty straightforward we have our title and our body reference we have the mutation here which is just calling create post and that's create post function all it does is it calls out to our API and creates a brand new post really super straightforward all these different functions they're just calling our API that's all that they do and then what we do is whenever we submit our form we're just calling the mutate function of our create post mutation and down here if we have an error we're rendering out that error we're making sure that if we're in the loading state that we render out specific text and we make sure our button is disabled so really straightforward stuff this is a super basic form and we've kind of already covered this at the very beginning of the video but I want to go a little bit more in depth on everything you can do with use mutation so like I mentioned you only need one property if you use mutation and that is your mutation function this is very similar to your query function it must return a promise and that's really all you need to know and this also accepts a first parameter which is going to be whatever variables you pass to create post so in our case we just do something like this there we go whenever I pass in here some variables that is going to be the very first thing that gets passed into my mutation function so down here when I call that mutate function right here you can see I'm passing in an object with a title and a body that's what this variable is right here is going to be now I'm just going to put this code back to what it was before it's a little bit more concise a little bit easier to read there we go that's all going to work exactly the same now the key here is that we have some different things we can pass in here for example we have an on success this is going to happen anytime we have a success this is going to take a function that has our data it has our variables and this variables is the same variables that you pass to mutate so it's just whatever you pass to mutate and then we are going to have a context as well I'll talk more about context a little bit later but for now it's really not that important it's just something that you can save and store across all of your different mutates for example I can set a context like this so on success we obviously know what that is we have an on air which is the exact same but we have error here instead of our data we have an unsettled this is kind of like finally if you're used to promises this is going to take in our data our error and then our variables in our context and then finally we're going to have an on a mutation or an on mutate sorry this one's a little bit interesting because all it takes in is the variables just like this and this is actually going to be called before your mutation function so if you have both of these set the on mutate will be called First and this is Gen finally where you're going to set your context so if I come in here and I just return like something that says hi buy and then I have an on success and I get that context so I make sure I go data variables context and I console.log my context that context is going to be whatever I return from on mutate and we can actually see this happening if I just come in here inspect my page go to my console you can see there's nothing in it currently if I click create you can see it's logging out High by and that's because that is my context variable which is set as the return value for on mutate so on mutate is really great if you need to do something before your mutation function or if you need to set some data inside your context another important thing to note about use mutation is if you make your mutation and it fails it doesn't do any type of retry like you would normally get with a query this is to make sure that you don't accidentally you know or create seven posts if it retries seven times even though it returns an error if it still creates it on the back end generally this is a good thing but if you want you can pass retry and you know say three and now it'll retry three times before actually showing as an error generally I wouldn't do this with mutations though and the next thing I want to talk about is important properties on the create post mutation object so we have our data so for some reason your API returns some type of data that's going to be available right here we have an error pretty self-explanatory we have our status and our status is going to be set to a few different properties here we have error we have loading and success just like with query but we also have idle and that's because the mutation can be waiting to happen because in our case the mutation doesn't do anything until we hit create so it's going to be in the idle State until we actually hit create we also have Boolean versions of these so we have like is Idle we have is error and so on is Success those you can use as well and then finally the very last thing I want to talk about is the mutate function which we already know super straightforward that's just what you call if you want to mutate but we also have an async version and this async version actually uses promises so we have dot then here and you know we can do a DOT catch and so on so if you need to do specific things when you mutate you can use the mutate async instead if you really want another thing to note about the mutate function is let's say you pass it an object it also takes a second object so you can do things like on success or on air in line for each individual mutation that you're doing generally I find that I don't need to do it this way and I prefer to set my on success in my actual create mutation here but if you need to do it at the actual moment you call mutate you can do that as well by passing a second property to the mutate function so to kind of understand exactly what's going on here let's say that whenever we successfully create a post I want to render the page for that post so let's get rid of this on mutate we don't need that we don't need any of this variables or context information we just need our data which is is going to be the post that we just created and what I want to do is I want to go to that post page so what I can do is I can make sure that I pass in the ability to set the current page and if we go into our main here or sorry our app we can make sure we just pass Set current page equal to set current page just like that so now whenever we create a post we have that being passed along and inside of here what we can do is we can set the current page to the current post that we're going to so in our case we want to render out post and we want to pass in the post ID that we're using which in our case is just ID it's just data.id I believe so now if I just make sure that I import this post object here there we go and now I save let's just say new post body is new and if I click create you can see we have an error looks like down here I just have to say create post mutation dot error so I messed that up so let's actually see it looks like we probably had an error when we created our post so let's just say a a great and that actually worked that time so I had an error for some reason but now I don't but as you can see it brought us to that post page and as you can see it's showing all the information for that post we go back to our list you can see that that data is there you'll notice something really interesting let me just refresh my page real quick I'm going to do an inspect and I'll create a post but after I create the post before I go back to my post list I'm going to turn us on to a slow speed so slow throat slow 3G and let's go back to our list we should have an ASDF ASDF on our list so I go to post list one you can see that there is one there but that's the old one and then it took a while for the new one to show up so let's create a brand new one this one I'm just going to call a bunch of these so it'll be really easy this will pop out if I click create you can see it's loading it'll then bring us to that page which is going to have some more loading for but now we have this post so let's go to our post list again you'll see there's no B post anywhere at all and then it pops up after a while that's because it's doing that refetching in the background forest and then it's getting the new data realizing the new data is different and then updating our UI with that new data now doing it this way is fine it'll work but it's not the ideal user experience I probably want to show that this is old data and invalidate this so that it'll reload every single time immediately this is especially important if you have an actual stale timer set up so your data doesn't immediately go stale this is because in validating the query will force it into that stale state so we come into here and I actually go back to what we had before we had that long stale time now if I just come and I look move over my camera you can see that this is currently in the fresh state it is no longer a stale let's create a brand new post we'll give this one a bunch of C's now click create and you'll notice if I go to my post list that does not show up and it won't show up until this data is no longer fresh and it becomes still which is going to take five minutes that's obviously a horrible user experience which is why you want to invalidate your queries and pretty much anytime you do a mutation you're almost always going to want to invalidate any query related to that mutation because you're obviously changing the data of that query so in order to do that let me just move my camera back here what we need to do is we need to import the use Query client hook this is something we've already done at the very beginning of this video so we want to get that query client from the hook there and we can call the invalidate queries and we can pass it in our query our query key which in our case is our post query key just like this so now if I just come over to my page and I inspect I'm sorry not inspect if I go to the dev tools and I look this is currently fresh I'm just going to refresh our page so we're super straight here we go we have a fresh query let's create a brand new post cccc cccc actually let's just make it a bunch of D's there we go click create and now you can notice over here my actual post this is going to be considered stale it is inactive right now and it is not fresh data and we'll be able to see that if I inspect my page go to the network we'll make sure that we go on the slow 3G go back to my post you can see it's refetching that data because it's stale and now my new value with this bunch of D's is showing up just like it should so by doing that invalidation we forced it to be marked as stale which meant as soon as it needed to be re-rendered on the page it actually showed up and rendered that data for us this will also have a slightly unintended side effect though let's say that we come in here I'm just going to refresh my page get everything back to normal and what I want to do is I want to query my first post so see post of one that is currently fresh data and now what I'm going to do is I'm going to create a brand new post it just doesn't really matter what this is create it and now what I want to do is I want to again throttle my page so we can do here slow 3G I want to go back to that first post you'll notice it's refetching that data and that's because this data is actually set to be stale and the reason for that is because of the way that we invalidated our data so let's just put this back to how it was with no throttling and we'll come back over to here move my camera over there we go you can see that when we invalidated our queries we passed it this post array just like this and what this does is it actually invalidates everything that starts with this in the array so every array that starts with post is going to be invalidated if we look here this starts with post so it's going to invalidate all of our individual queries here as well this is why when you do invalidation this actually takes a second argument with a bunch of different filters that you can do and in our case if we say exact true that means it's only going to invalidate the query that has that exact query key right here instead of just starting with that query key as you can see there's also a bunch of different options here for different things that you can reset if you want to it's entirely up to you but there's a bunch of different things you can do in our case we just really care about exact true and that's what we want to do right here now another important thing to know about mutations is if we go back here I'm going to make sure we throttle this page to be really really slow again what I want to do is I want to create a new post it doesn't matter what the name or title is but you'll notice when I create this post it when it goes to the page of the new post it needs to reload and get that data so it's pretty slow and the reason for that is because I don't have that post in my cache but at this point when I finish my mutation I obviously have this data so there should be a way for me to put that data into the cache and luckily there's a way to do that with react query and this is called manually updating the cache so what I want to do is I want to take my query client and I want to specifically set some query data so in our case I'm going to set query data and this query data is going to be for post and I'm going to do it at my new post dot ID or actually data is what I called this so this is the query key and then I want to actually use the data I'm going to use at that query key which in our case is new post so now what I've done right here is I've created a brand new post inside of my query so with this one line of code does right here is it allows me to create a brand new entry in my cache that is pointing to this query key with this data so now if we just make sure that we're still throttling our page over at our Network we're in a slow 3G let's go over to create a brand new post I'm going to create a brand new post doesn't matter what the data is and when I click create you can see it takes a while to load but as soon as it gets to this page you can see the data shows up immediately actually it looks like we had an error if we go to our console you can see new post is not defined this should say data instead there we go so let's try that again let's quick create give it a second to load everything and then you can see when it gets to our new page it'll actually show the data instantaneously any second now there we go you can see it instantaneously showed that data which is great it still had to load the user because that wasn't in my cache but all the data for the post was instantaneously showing because it was already set manually inside of my cache now the only other thing that you can do with this set query data is you can actually pass it a function and this function will take in the old data as its property right here that's really useful if you need to make changes to the old data by passing in some new data so I could you want to combine together the two things the only key here is that you need to make sure that you don't change the old data you can't mutate it it must be immutable just like when you're working with react state so that's one other thing you can do but most often you're probably just going to be passing in the data just like this now the next thing I want to talk about is pagination as well as infinite scrolling and first we're going to be talking about pagination so if we go over to our app you can see I've created a brand new page called postless paginated if I go over to that page this is very similar to the code that we have for our normal post list as you can see if we scroll down here our data for our post is rendering exactly the same you can see our post list paginated is showing up right here the only difference is very few things instead of how we actually use our query so you can see the very first thing of note is that when we're doing our query key I'm passing in a page as an object here and that's because when I'm on my paginated page here if I just click on this let me make sure this works looks like I just need to come over here and make sure I import this there we go so now if I go over to this page you can see it's showing two at a time and I go next next and so on and previous just like that everything's working just fine so if we go back to this post list paginated the main difference is I'm passing in the page as part of my query key because obviously I'm changing the data and you also notice that I'm passing in this keep previous data key here and the reason why this is really important is it's going to show my previous data while it's loading the new data which is really important this will just make it so when if I just refresh here go back to this when I click on next it won't show the loading State it'll still show my old data and to make sure we can see that I'm going to comment out this little bit of code here but you can see as I click next if I slow down my page speed so we'll just go down to throttle this I click next you can see the old data is still showing up still showing up and then the new data shows up still shows the old data and then boom the new data pops into place and obviously if the data is cached it'll show up immediately so that's really useful now if I bring this line back in that I commented out you can see here when I click on next and go to a new page you can see it's showing that I have the previous data being loaded right there that's just because I have this Boolean called is previous data this will show up when it's loading the previous data or when it's showing the previous data and trying to load the next data this will be true so I'm just showing that that does right here really though that's the only thing that you really need to worry about for this also you're going to want to know if we have a previous page or a next page I just have this baked into the API it's going to tell me if there's a next page or a previous page it's returning as part of the data but really the only thing you need to change when you deal with pagination is you need to put the page inside the query key you need to make sure your query function deals with the page and you need to set keep previous data to true and optionally you can use this as previous data otherwise everything stays exactly the same so pagination is super easy with react query now the next thing I want to talk about is infinite scrolling I've changed our code to add a button to go to this infinite scrolling page and the code for this is slightly different so I'm going to take a look at it in depth but if we just come to that infinite scroll page you can see we can click load more and it's going to constantly load more and more data for us looks like there's a slight bug in my code here the page param should be set to 1 by default not zero but let's just refresh that go back here you can see now it's working just fine it's constantly loading more and more data and if we slow down our page we can actually see what's happening behind the scenes if we click load more you can see it says loading and then once that's done it'll show the data and so on and it'll do that until we run out of pages on our thing to load as you can see right here I ran out of pages so there's no more buttons showing up so I move my camera you know you can see what exactly is going on so understand how this code works we need to use a different query here we're using a use infinite query hook instead of the use Query hook and this Hook is very similar it still takes in a query key it still takes in a query function those are exactly the same but the biggest difference here is it needs to take in a get next page print and this is just a function that returns to me what the next page is and that is being returned by my API so this will take in our previous data which is the data for our API call that's currently rendered on the page and we just return whatever we want so in our case I'm just returning the next page because that's returned by my API it actually Returns what the next page is another important thing to note is our query function now takes an additional object inside of it which is our page param and this page print is just whatever is returned by get next page param so we can use that when we get our post page I'm just using that paginated request so to really understand what's going on here is whenever I try to load the next page what happens is it calls this function and gives me a page number for what the next page is it then passes that into my query function right here is this pagepram and I use that to actually get my next page of data so that's where the biggest difference with calling use infinite query comes in the other big difference is how you actually use the data so we have our typical status error data those are really normal but we also have this is fetchy next page has next page and the fetch next page function this fetch next page function is just what you call whenever you want to get more data so on our button we're calling that function right here the is fetchy next page is like our loading state to determine if we're loading our data and then finally our very last thing has next page just determines if we have another page so if this returns to us undefined that means we have no more page so this will be set to false otherwise if this returns any value it'll be set to True another important thing to note is our data property is slightly different than it used to be it's now broken up into pages and each page represents the data for that individual page so we have Pages being shown as well as we have here page params and that's the actual param we got for the individual page so this would be like one two three four for what page number we're on it's just the thing that's returned from right here so we need to make sure we do our data slightly differently because we need to Loop through each individual page another important thing to note is we can actually go backwards by getting previous data by using the get previous page param which works exactly the same as next but it's for previous we also have the has previous page and is fetching a previous page as well if you wanted to go forward and backward with your infinite list now that covers all the basics related to react query so I want to cover a few Advanced features that are really useful that you're probably going to run into with your projects and the first one is the use queries hooks which is very similar to use Query but it's one you need to run multiple queries at once let's just go to my post list page and what happens if I want to run a query for each one of my posts that I returned from here well you would think I would just do a post query and then I would get the data and then I would map through that data and for each post I would run a query inside of here like this but the problem is you can't use hooks inside of anything like a function for mapping or a for Loop or an if statement you just can't use hooks that way so to get around that you need to use the use queries Hook and the use queries Hook is very similar to use Query but allows you to just pass it an array of queries that it's going to run so I can do the same exact thing here right map through my data for each one of my posts so I could say for example post like this and I want to make sure I pass this as my queries property just like that there we go so inside here I just need to essentially return an object and this object worked just like the normal use Query that we have so for example we have a query key which in our case is going to be post and it's going to be post dot ID we're also going to have our query function which in our case is going to be git post there we go and this get post function needs to take in our post.id there we go so we're passing it all the normal things we would pass to our query itself then what we could do is we could actually get those queries so we could say const queries is equal to this and I could just like say console.log queries dot map and let's say that we wanted to get the data for example so we could just get the data from all of our different queries like this if I make sure I put in some question marks inside of here hopefully this should work I just give this quick save go to my post page one of course it does not that's because if this data is null I obviously want to return an empty array so we'll just say we're going to turn an empty array if this data does not exist and there we go now we have our post list showing up and if I inspect my page and I go to the console you can see we get an array with 17 different data values all of them are undefined it doesn't really matter what the data is but it's showing you that it does work it's because git post is not defined there we go so now if we inspect our page hopefully that should work we have arrays of values if I refresh our page you can see that now it's showing all the different data for all of our different objects because it's querying all of them for us so if you need to do a bunch of different queries inside of an array you need to use use queries instead of using an actual array syntax and then you pass the array inside right here this is much more common if you for example have a list of IDs that you want to render you probably wouldn't do it in a scenario like this another thing that's really common that you may want to do is actually pre-fetching data so let me just get rid of all this nonsense that we had here everything is working just as before there we go I want to go back to my main app page and let's say whenever I hover over a link I want to actually query the data for that so when I hover over my first post I want to actually get the data for that by pre-fetching that data so on Mouse enter what I want to do is I want to call on Hover post one link which is just a function we'll create up here on Hover post one link and what I want to do is I want to pre-fetch my data and to do that I need to get my query client so I can say query client equals use Query client which I'm just importing right up there query client dot prefetch query and where you work this is you just pass it in some options so we have our query key query key this is going to be for our host at the very first index and then what I want to do is I want to pass it a query function which in our case is just get post make sure I import git post there we go and this get post I'm just going to be passing in one so what this is going to do is it's actually going to pre-fetch my data so essentially it's going to pre-populate the data inside my cache whenever I hover over this link which is when I call this function so to see this actually working let's go ahead and open this up I'll bring my camera out of the way here and what I'm going to do refresh the page so we have a fresh slate here I'm going to hover over first post you can see it immediately fetch that data it showed up right here so now when I click on that page you can see the data is already there it doesn't need to refetch that data this is really useful because you can actually say oh is the user going to need this data soon I'm going to pre-fetch it in the background for them that way when they go to that page it's already going to be in the cache and loaded for them now the final thing I want to cover is how you deal with initial data and placeholder data so let's just go over to my post list that we have right here and what I want to do is I want to say that we're going to have some initial data so I can just pass in initial data here and let's say my initial data is going to be an array it's going to have an ID of one and it's going to say a title of initial data just like that so now if I go to my post list one just refresh my page you can see it first shows my initial data you'll also notice it's not actually doing any other fetches and that's because when you set initial data that's saying that this is legit valid data and it's being stored in the cache and this data is no longer stale because we have that stale timer so as you can see this data is actually set to fresh right here that's really important because if you put placeholder data inside of there like we've done in this case it's going to persist as part of your cache so if you want to use placeholder data just set placeholder data instead and now if we refresh our page and we make sure that we throttle this to be a little bit slower so it's not quite so fast and let's move this over here there we go so if we refresh our page it's going to take a while for it to load for the very first time but what you'll notice is that it's first going to show us the initial data and then it's going to load up our post and then it'll show us the actual data from getting the post so first I'll show placeholder and then it'll show the newly fetch data that's the difference between placeholder and initial data is placeholder data will be immediately replaced by whatever your query is is essentially always marked as stale while the initial data is going to be served and saved inside of your cache and it's going to be marked as fresh if you have some type of stale timer set up so now that that finished loading you can see we had our initial data there very briefly and then it actually showed our current data that is being rendered and that's all you need to know about react query now if you enjoyed this video you're definitely going to love my full react course where I deep dive into react just like this but everything you need to know about react that course is going to be linked down in the description I highly recommend you check it out with that said thank you very much for watching and have a good day
Info
Channel: Web Dev Simplified
Views: 275,744
Rating: undefined out of 5
Keywords: webdevsimplified, tanstack query, react query, tanstack, react query tanstack, react tanstack query, reactjs, react js, react.js, react js query, react query js, reactjs query, tanstack react js query, tanstack javascript, typescript
Id: r8Dg0KVnfMA
Channel Id: undefined
Length: 51min 8sec (3068 seconds)
Published: Tue Jan 17 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.