Learn Tanstack Query - Full Course for Beginners

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this tutorial you will learn everything related to T stack query formly known as react query after watching this video I guarantee that you will understand every concept of this library and will be able to confidently start working with it you're going to learn all things about queries mutations invalidations infinite scrolling paginated queries chained queries and almost almost any Concept in this amazing featureful Library so let's get it started to get it started we need to create a simple react project using vit if we choose react here top ISC and that's it after we initialize our project we need to install our dependencies using npm install and after that we need to install our required packages and other dependencies first of all we need an HTTP client we're using axus here the tanack library itself and also its Dev tools and also we're going to install react hook form to create just a very simple form for our project hit enter after that our packages installed successfully we need to also install a very simple Dev dependency for our project it's called tack es lint plug-in query don't forget to add def flag to install it as Dev dependency for our project this Plugin or other ESL plugins help us to create better code and write better projects hit enter by now our package.json file must look something like this and also note that I'm using note version 20 here then we need to config our ESN file here open your eslint file then paste this line here to make our project know about the es plugin library that we just installed for tanack also we need to put tan stack query plugin in the plugins array and that's it that's the setup for our project here so let's get it started but before we continue please do not forget to like And subscribe as it really helps my career on YouTube to continue now open the index.css file remove all the content inside it to make things simpler then go to app. CSX then remove all of it and just put app here to make sure our app is working also delete this user State and also redundant Imports and this app CSS here run the project here and as you can see our app is running successfully to understand that how this library is going to help us is to create a very simple get request in our application the old way of using it I'm also running a very simple backend server for my application to work you can download the whole project in the description below as you can see here there's a very simple escript that is running this dp. Json file here on the port of ad8 I can access todos from here I can access projects by this endpoint also I can post put patch and other things on this fake database also I added a 500 milliseconds delay to simulate a real project because in real world we're going to have a delay between our front end application and our backend application so let's get back to our project here I'm going to create a very simple get project using axus here the old way of using it I'm going to import use effect from react then inside it I'm going to import the axio instance here I'm going to use HTTP get method here and address of my API HTTP Local Host ad ad and the end point of toos as you can see here the too end point is going to return return an array of toos which has the checked Field title description and an ID then I need to create a data State data set data and I'm going to use a user State Hook from react here and then initialize it with an empty array then I'm going to use a response here to set my data with the response data and also I'm going to any error like this I'm going to L it on the console here and then I'm going to show the data in my react project like this I'm going to Str stringify the data here like this as you can see here I have my toos here but as you can see this way of using it is not very flexible because we need to H because we need to handle the error here we need also and also for example if you want to create loading estate for our request we need to also create loading Estates using react use estate hook or other hooks we need to handle error refreshing data revalidating cash and so much other Boiler code here this is a tip of the iceberg here and if our application escale grows it's a nightmare to handle all these requests caching revalidating mutating the server State and more but Tac query library is here to rescue us for better organization I'm going to create a surfaces folder here then I'm going to put all logic related to the data fetching in this folder first of all I'm going to create an api. TS file here and in this file I'm going to talk with my backend server imagine that my backend application has an endpoint that returns all the IDS of all toos we're going to use cons get todos IDs here this is an async function because it must return promise here also don't forget to export this function from this file then inside the curly braces I'm going to return a promise but for better organization I'm going to create base URL for a backend server here which is Local Host 80 and also to not repeat myself every time that I'm going to use axio I'm going to create a very simple axio instance here cons axio instance is equal to axus do let me import the axus here axus do create for base URL argument I'm going to put this base rer that I defined here then inside the get Todo IDs function I'm going to use await axio instance. getet and if you remember that our backend returns a tutu like this it has checked title description ID Fields I'm just going to copy an example of it here then inside my application in the SRC folder I'm going to create another folder called types here for better organization then inside that I'm going to create a 2o. TS file and inside that I'm going to export an interface called to-do here which is exactly the schema of my backend project to-do the check is in bullan type title is string description is also string and the ID also is number it might be optional I'm going to explain it in a second and This Promise is going to return an array of the suus that we just defined here in set the URL we need to put the toos endpoint here I'm going to put parentheses around this evate here dot data which is a response of our backend here and then I'm going to map over the data here like this and then for each item or Todo here let me just change it to Todo here for you to better understand I'm going to return the too. ID here this function is going to return something like this 1 2 3 4 it's Etc just a quick tip just you know always use axio rather than using the native JavaScript fch API because the axus throws errors for unsuccessful HTTP call automatically but fetch don't just keep that in mind now we can use this function in our application to get the todos IDs of our backend server but we cannot just simply uses get to do ID's function application we need to use the 10stack library again for better organization I'm going to create another file called queries. TSH here inside this file I'm going to write my application query functions for example if I'm going to use the toos IDs in my application I cannot simply just use this function in my application I need to create something between my application and my API responses to handle caching revalidating errors loading Estates pending Estates and much more so inside this file I'm going to export a simple H called use toos IDs and inside it I'm going to return a use Query Hook from the 10stack react query library inside this object we can pass many options and configs here but at minimum we need to put the query key and query function here I'm going to explain you in a second query key is equal to todos and also our query function is equal to get todos IDs the function that we just described here just forgive my mistake I must use function here as you can see here we use Query key and query function the query function always must return a promise as you can see here if we returning a promise from this function and the data which is obvious it's an array of numbers array of IDs here and the 10 sa library is intelligent ENT enough to guess the types of the return of the function as you can see here the type is an array of numbers and also undefine because it's intelligent enough to Guess that the server might not response the server might not respond us with the data and in that situation our data is going to be undefined but what is this query key here we can put anything in this query key here for example I can put IDs here too or todos but it must be something that you remember it very well because we use this key to revalidate our query here what does it mean imagine that in your application you create another to-do and you expect that your old list of to-dos refresh again but your application is not smart enough to guess the behavior like this we need to somehow tell our application to refetch that query I'm going to explain you this query here in detail in the mutation section also we have another options here for example we can use refetch on window Focus to false because false because the query will always be fetch if the user lose focus from browser from your project for example if he goes to another tab then returns to your project the query will again be fetched also we can enable and disable this query here using enabled property here which it can be false or true or for example you can pass Thum pass something here for example is an bullan and then we put it here and if it is true then the query is enabled and otherwise it's not just remove it for Simplicity here and remove this this is our first query in the project then we need need to head over to our app. TSX file remove all these codes we do not need them remove redundant import and also this here inside my app. TSX file I'm going to use a react component here called todos I did not create it yet so inside our SRC folder I'm going to create another folder called components here then inside it I'm going to create file called to. TSX here which is a react component here export default function and it's going to return nothing at this moment but we need to use a query that we just wrote there so cons toos IDs query is equal to use too ID that we just defined there this simple query has so many features and options that I can use in my application if you see it you can see I have the data here I can check if there is an error or not is error is my query fetched is a query fetching is loading is my query passed is my data stale is a query successful and many more options to use them for example I want to know whether my query is loading or not if my query do is pending then I'm going to return the loading here we can use it in another way like this instead of e paining I'm going to use status is equal to pending success or error but I prefer this syntax much more or if my todos has an error I'm going to show a message to the user which there is an error now the library is intelligent enough the typers script knows that if a query is not pending or is not in error State then it must be in success phase now at this point of my application I know that always I will have the data here so I can map over my data like this to do query. data map to do no ID here and inside that I'm going to show simple paragraph which inside is the ID of the too I'm going to use the ID as a key here but if we head over to the browser to see our application we see that it's not working because we forgot to initialize our application with a query client it's very simple just open your main. TSX file here and we need to wrap our app component inside a query client provider like this query client provider here put your application here then import it like this query client provider this package here also I need query client itself and also I'm going to import the react query Dev tools which is a very powerful tool to debug your queries and mutations I'm going to import it from this then I need to create a simple query client like this query client is equal to new query client like this and also I can change the default config here for example can use default options here then inside it for my queries for example I can to change the retry Counts from 3 to five because by default react query tries your request three times if an error occur for example I can change it to five if request to the server fail the tack will retry it for five times to make sure that there's nothing missing out also I can change the retry delay here for example I can change it to 1,000 milliseconds and many many more option enable that we just saw in our query that we just created for example refetch on window Focus that we saw earlier and so much more we can customize our query config at the root level of our application after that we need to pass this query client inside the query client provider like this also do not forget to put react query Dev tools here and also passive prop initial is open to false because we do not want to open this Dev tools every time that we open our browser then head over to the app the TSX file here and import ort the too here and as you can see if I open my backend server here we have two todos here one with id4 and one with id6 as you can see here I fetched my IDs here and then if I reload the page first you see a loading estate which is here and if an error occurs you will see this message there and if the query estate is not in pending or error status then the data will show here as you can see we have the ID 4 and the id6 and if you each time refresh the page you see loading estate and everything is handled for us with no other boiler plate code we can also use this query like this we're going to use object Destruction for example I directly get the data here I can put it like this also I can use the is pending estate and is error State here like this then remove these redundant codes here and that's it but I prefer the old way of using it like this because in a file we might have several queries and this way of doing it is not very applicable to see our query States better I'm going to put the query function status here which is a toos query. F status and as you can see here it is in idle mode the function that is getting our data I'm talking about this function here is in idle mode because this function is not running at the moment because it has fetched it St data if I refresh the page just let me remove these codes here because we do not need them anymore but as you can see here because we did not specify the is pending and is error States here the typ script is telling us that query might be undefined and which is true we can use the question mark here to tell type of script that we know it might be undefined and if it is defined use this map function over our data as we can see if I refresh my application first from the application loads you see the fetching estate which tells us that this function is running at the moment as you can see here it's wiing and now it's idle also we can see our query data let's say this like this to this ID query. status as we can see the data now is in success mode and if I refresh the page first the page starts it's in pending mode the two main difference between fetch status and Status itself is that fet status is about the function of the query the function that is responsible for talking to the back end which returns a promise and also the status about the data which is in success pending or error mode that's it also we have a very simple but yet powerful Hook from Tannis sary called uses fetching hook call is fetching is equal to use is fetching which I'm going to import it from tasac itself is fetching from this library and I'm going to use it here with the name of global is fetching is fetching as you can see it returns a number between zero and many queries that are fetching at the moment it's very helpful if you want to know that your application is fetching data or not now if you open your Dev tools here you can see your query here that is in stale mode if you open your query that that we just wrote earlier we can see that this too key here is actually here and with this amazing tool we can see our query estate for example if I refresh my page you see on a start my query is fetching the blue indicates that our query is fetching if I refresh again you see that so just close it then we need to head over to our application here I just need to add ID to know that these numbers are the IDS of our toos and then I want to comment these lines here for Simplicity also I need to comment this and that's it this is the idas of our todos but what if you want to get each too completely by its ID it's pretty simple with this library now that we have the IDS of todos we can simply fetch each to-do one by one how to do it for you to see better I just need to head over to my back end and add a few more toos like this like this I make this idid 1 iD 2 3 four just a few more this is ID 5 6 seven and eight here then I just made the twoos a little more descriptive by adding title and correct description like this I need to again run my server like this and that's it we head over to our application and as you can see here we have a to do that we just created just imagine that you have an API that returns a complete to-do by its ID we just need to head over to the api. TS file then create a simple function called get to do here like this it's an Asing function which accepts the ID of the too which is a number then we're going to return a promise like this evate xuse incense. getet it is the type of the to-do it's in the in point of too slash I just need to use I just need to use the string format like this then I just pass the ID like this this end point return the whole too by its ID then at the end of it I just need to put it in a brace here then I'm going to get the data like this then in our queries. TS file I need to get the toos by their IDs one by one how to do it it's very simple be react query I'm going to create a simple hook like this function use toos because it's going to return our complete toos then inside the curly bases I'm going to return use queries book from the T query library but import it just like this use queries and then that's okay the difference between use Query and use queries is that if you want to fetch multiple queries that we do not know how many of them are we can simply use this hook the syntax is like this we put queries here we need to get the IDS from our us toes like this which is an area of numbers or it may be undefined also the number might be undefined too just like this then we need to put the IDS here we're going to map over it remove the braces here ID at map and we want for each ID to do something we put ID here is equal to open the car says and we are going to return a simple query I'm going to put query key here then for key I'm going to consider to-do for its name then I'm going to pass the ID after that for the query function as you can see the pattern here this is exactly like defining the simple query but the differ between this hook and this Hook is that this returns multiple queries and for each query we can use a function that we just defined which was get to do just like this and we put the ID here and by this point we know that the ID at this point is defined so we put exclamation mark to tell type of script that we know that this value is always defined I realize that type of script is throwing us an error we can simply solve it by putting the IDS in the braces in braces then like this we can tell if the IDS are defined then map over them and if not map over an empty array and at this point won't do nothing that's it now we head over to our react component here then I'm going to let me just remove all of these for Simplicity completely then I'm going to initialize the hook that I just wrote todos queries is equal to use todos like this and for its argument as you can see here we need to pass the list of our to-dos IDs which is this query here query data here to-do IDs query. data then below it we're going to we're going to map over it like this. map and this going to return the data like this and then inside the return of this map function let me just put another brace here then we need to map over our Todo queries like this Todo query. map and for each iteration I can get the data directly like this then I need to return a list item like this don't forget to put the key for react to work better data. ID is my key then I need it to be an on order list like this inside this list item first I need to return ID of my to-do like before data. ID below it I'm going to create a simple span I'm going to use a strong HTML tag here then I'm going to specify the title here and in front of it I'm going to put the data. title like this and simply I'm going to add the space here Bel it I'm going to use Str again for description of too and in front of it again I'm going to put data the description like this as you can see here our application is not working because I did a simple mistake go to your api. TS file then instead of too just use toos here and if you refresh your application you can see that each to-do is going to fetch one by one and in parallel which is very good for performance if I refresh again my page again you see first the IDS are fetched then for each ID as you can see you're getting the hold Todo like this if you want to multiple queries that you don't know how many we can use this solution then I'm going to remove this here for Simplicity and that's it till now we just only talked about the queries but what if we want to add a new to-do or edit a to-do or delete a to-do instead of queries we're going to use the mutation concept of T query in this Library there are two major ways that you can communicate with your backend one is queries and another one is mutations when you are using queries you want to read data from the server but when to use mutations when you want to change the estate of the server for example add new item delete new item delete an item or update an item imagine that you want to add a new to-do to your list for better organization again in Services folder let me just make it bigger you're going to create another file called mutations. TS here inside that I'm going to create a simple hook like this export function use create to-do and the syntax is like this we're going to return a use mutation Hook from tquery inside it we're going to get a mutation FN or function which gets data which is my to-do then do a function which I did not Define it yet so let's head over to the api. TS file here in here I just need to create another service for my application like this you're going to use export const create too is equal to async data which is of type too because we are creating too then inside kber says we're going to going to return anything we just want to do something and the 10 library is smart enough to handle errors success or other states for our request or our mutation we simply need to do something here the thing that I want to do here is to create a to-do on my database how like this A8 axio instense post to the end point of to-dos and my to-do which is data here then we need to head over to our mutations then I'm going to create to-do like this and put the data as an argument if you use this hook in your application you simply will create a too which is not a very special thing to do power of 10 SEC query library is here we can simply intercept our mutation function at any of its life cycle we can use unmut here then it returns a function then it will do a function for example I can like that I'm in mutate state which this function will run before our Crea into the function for example we can intercept our error simply like this if our mutation gets an error this function will run like this for example I can cons like error here then I have six here that if your mutation is successful this function will run like this console. log success and another one is unsettled I'm going to explain you in a moment that what are these and how they can be helpful unsettled is also to a function here like this and then I'm going to log the console. log settle here for you to see better in a moment why are they useful you can intercept your mutation in each life cycle for example even before my query function starts we can simply intercept it by using this un mutate here then if an error occurs you can simply run this function here or if it is successful then we can run this function and whether it's in error state or success State this unsettled here will always run end of your mutation so if I head over to my application in my to the component here I can simply use this hook to create create a new to-do like this const create do let me just const create too mutation mutation here use create too like this then I need to create an Handler for it like this a very simple Handler handle create to do Summit because after submitting my form which I did not create yet I'm going to submit my form like this I'm going to import the submit hand there from react to that we just installed then I'm going to pass my to-do interface here then as an argument I'm going to get the data from it which is my to-do it will make sense in a second then inside the curl braces I'm going to use create mutation create to the mutation. mutate and I'm going to pass my data where does this data come from if you open your mutation hook like this you can see that inside our mutation function you pass the data which is of type to do this is exactly the thing that you pass on mutate function of your mutation but to make things work we need to create a very very simple form just to show you I'm going to open the form tag of HML then on submit of it I'm going to submit my form and before that I'm going to initialize my form like this cons open the curly braces here you're going to use the use form Hook from react to hook form I'm going to import it like this import use form from react hook form then I'm going to pass the too like this as a interface for my form I made a mistake the both too interface and the too react component are the same so I'm going to change the Todo component to todos just hit F2 then change it to todos then open its file also and then change it to todos instead of to-do then head over to your app. TSA set and see if everything is working correctly save it then inside it we're going to import the too here and from this hook I'm going to get the register and handle Summit it's not related to T side query but it's not related to T side query but to make a simple form we need to do it and that's it these are everything that we want from the use form hook then inside your form let me just close this primary inside the unsubmit I'm going to use the handle Summit this one then I'm going to pass my handle create to to Summit here and inside it I'm going to create a simple input let me just put an H4 tag here called new to-do then for this input I'm going to use the placeholder of title because it is the title of our to-do then I'm going to put register here like this then I'm going to register it with title and if I copy it here like this I'm going to change it to description also this one to description I'm going to put a Break Tag here for better organization below it again I'm going to use another Break Tag then I'm going to use a summit input going to use the type Summit for it and that's it if we head over to our application we can see our simple form here if I put a test title and a test description here and if I click on submit query and if I refresh my page I can see that new to-do is added here but there is a problem the problem is that that every time we create a new to-do we need to refresh our page the react is not smart enough that we create it then the list of our toos need to be updated we need to somehow tell the TAC query library to update our list of too after the mutation the create to the mutation is happened how to do it it's one of the main Concepts and one of main features of T side query Library it's very very simple you just need to head over to our use create to do hit F12 on this go straight to it as I told you earlier this unsettled function will always run it has an error or not so it's a very good place to tell the T secare library that we need to to invalidate or refr a query which here is our list of to-dos because we added a new to-do and for your information we can get many useful things from this function all of them we can get same things for example on settled I have access to data which is the thing that your mutation function returns or I have access to error here this is the error that raises when your mutation fails and another one is the input of your mutation function for example by convention it's called variables for example you can get the input of your mutation function in the unsettled function which is which can be helpful in many situations for example if I use variables do you can see the intellisense of type a script here which this variable is exactly the data that that we pass to our create to-do function these are very helpful things in tquery library but for Simplicity I'm going to just use the error here I'm going to remove the variables here and because I don't need it I'm going to Simply put an underline here I forgot to show you something about this mutation function if I open the console here let me just make it a little bigger if I open my console here you can see after creating a too you can simply see which function runs first as you told before the mutate here or the mutate here is going to run before the create to-do function success is going to run if the create to-do function is successful and unsettled will run no matter what no matter the state if it's Error or success it will always wrong then close your console here I'm going to put it here let's get back to where we started at this point the problem was that when we create a new too here for example a new too here the list won't get updated and I need to refresh my page which is not an ideal way of doing it so on the unsettle function I can say if there is an error then console.log error and otherwise at this point I know exactly that my query is in success estate so I put else here open the cly braces then here I can invalidate or tell the T query that go and again fetch this list automatically in the background how Above This hook here I'm going to get the query client like this use Query client like this then I'm going to import it from tanai query this is a very powerful API that you can anything with your query client cache State queries mutation and so much more inside our else statement I'm going to use the query client do invalidate queries the syntax is like this open the curly braces put query key here and inside that I need to put a query key here but what should I put here if you head to the queries here you can see that your toos ID's query key is todos so I just need to put this todos key here don't forget to put a weight here and make this function a synchronous because revalidating your queries oh sorry I just need to put the async here because invalidating queries is an async operation and it might takes a while to do it so after this if I create a new to-do I put new to-do here for its title and description and if if I put Summit here let me just make it a little bit smaller and as you see the new to-do is added here without the need of refreshing the page if again I do it you can see that the new to-do is added here automatically or in other words our list of to-dos has been updated successfully without we doing it manually because we invalidated the to-dos key here which is going to refetch again the list of toos in the background and if it's ready it's going to replace the old list with it seamlessly and it has an great user experience because the user did not see any loading Estates till now it's using the stale while revalidating cash strategy it means that user will see the stale data stale cash until the new data is fetch in the background then it's going to replace the old cache with new data and user won't see any gap between these transitions it's a very amazing feature that makes this Library amazing to make our implementation clear if you have noticed here if I click on this Summit query it won't respond to the user that a new mutation is running so we don't want our user to submit another mutation while the old one is mutating how to solve it is pretty simple I just need to disable my Summit button then my create to the mutation is pending it's much simple then I can also change the value of this input based on the a state of my mutation create to the mutation that if it's in pending state I'm going to put the creating text here when it is not in pending mode I'm going to put create to-do here create to-do simple and if I again hit on this create to-do you can see the creating text there and after that the new to-do is created and the to-dos list is invalidated it will get enabled again if I make it smaller to see all the toos here if I create on this we can see that when it got disabled there was no to-do at the end of this list and and when it got enabled the to-do was added to the server and the to-dos list were updated after creating our to-do imagine that we want to update that single to-do the difference between updating and creating a to-do is that when we create a to-do we add a new item to our previous fetch to-dos list but when we are updating a single to to do we only need to update that single to-do instead of the whole list it's pretty simple just head over to the mutations file close it then we want to create another hook another hook like this export function use update too like this then inside it I'm going to get my query client like this use Query client then again I'm going to return use mutation Hook from tack I'm going to put the mutation function here which I did not defined it yet so head over to your api. TS file here create another function here called const update too pretty straightforward async I have a typo here update Todo for the arguments of this function I need to pass the data also which is of type to do then in the Cur Library say I'm going to do something which is weight axus instense updating is of type put in HTTP in my too's endpoint I'm going to put the data. ID which is the ID of my too that I'm currently editing now and for the data for the body of our request I'm going to put data here we head over to our mutations. TS file then inside it I'm going to get the data from the component and pass it through this function that I created like this unsettled I want to do something for the arguments I don't need the data which is the response of my function like this I'm going to put underscore here because I'm not going to use it I want error then variables which is the input or exactly this argument here which is going to pass to the unsettled function on the third argument you can call it anything I'm going to open the Cur Braes here if I have an error I'm going to log that error pretty straightforward for else Clause I'm going to invalidate the list of to-dos also and the single to-do itself like this invalidate queries query key is to do here then for the ID of our query I'm going to put ID is equal to variables. ID as you can see I get the intelligence that on this type of variables I'm going to have check description ID and title exactly that we have defined here while we put this key here if you head over to our queries file here then I'm going to put it side by side as you can see we defined each query from our used toos hook with this key it has an too here like this and an ID like this but there is a problem but there is a problem here because it's better always to put your keys inside curly braces your Dynamic keys for example like ID or the count and other fields so to recap here we are updating a to-do after it is done I know that the list of to-dos were updated so I need to invalidate it also my single too has been changed also so I need to revalidate that single to-do also like this then if we head over to our Todo file here like this I'm going to initialize the hook that I just created update too mutation use update to-do like this now I need to create a simple handle function for updating my to-do like this handle update do submit which is of type submit Handler from react to form then I'm going to pass my too here like this inside the call back function I'm going to put data and inside that fun function I'm going to update to do mutation do mutate and I'm going to put my data here like this it's not correct I must do it like this and the only field that I want to change while I'm updating my to-do is that the only the checked property whether my to-do is done or not for Simplicity I'm going to change my check field to true and to make it more clear I'm going to change this function name to handle Mark as done Summit you'll understand in a second then if we come here after description and this span I'm going to create another div like this I'm going to put a button here and unclick of it I'm going to use the handle Mark as done submit function then I'm going to pass the data seta that I'm mapping over it if you hover over this error we see that type of script is is throwing us this error that data might be Todo or undefined so if I go to the definition of a function I simply need to remove this this to put a I'm going to put an equal sign here then for the type of my data I'm going to put the to-do or undefined and before submitting I'm going to check the if data is there then after that I'm going to update my to-do and if I head over to this section again I can put a text for this button like this if data. checked is true I'm going to mark it as done otherwise I'm going to put the label Mark as done here then I'm going to disable this button while if the to-do is checked then if we head over to our application we see that some of our tools are done and some of them are not for example and now if I put on this button here after delay of 500 100 milliseconds you see that this query is done and the leas and only this item was revalidated in other words it's mean that the list did not get updated and only one of these to2 get updated if I click on this and this you can see it does not have a great uix because when the user clicks on this he expects that a loading indicator or something else appear here but for Simplicity I'm not do it here what if you want to delete our to-do it must be pretty simple by this point of tutorial if you head over to our API we need to create another function const delete to do like this async it only get an ID then inside the CR braces I'm going to put axus sorry await axio instance. delete my todos endo and I'm going to put the ID here if we head over to the mutations file below it I'm going to write another simple another simple H here like this function use delete too I'm going to again initialize my query client is equal to use Query client like this and I also want to return use mutation hook for mutation function I'm going to pass the ID which is of type number then I'm going to delete too here like this un success I'm going to lock a simple console. lock here for example deleted success successfully and for unsettled which is also of type async I don't want to get the response of the mutation function result I'm going to use only the error side of it if error I'm going to again like the error on the console on else clause it's exactly the same as creating another too we want to update the list of toos like this await query client. invalidate queries and for query key I simply need to put to key here that's it for our use delete Todo mutation function then we need to head over to our file here const delete too mutation use delete too here then if you head over down after there the mark as some button here I'm going to put another button here with the takes of delete on click of it I'm going to create another simple Handler function for my deleting operation handle delete too is equal to this function ID is going of type number then I'm going to simply delete my to do like this put ID here and if we put our Handler here hand the delete and I'm going to pass the ID here as you can see here the typers script is throwing us this error that ID might be undefined so I just need to Simply put the section in CR verses like this if data. ID was not undefined or other wordss it was defined I'm going to return this button then I'm going to remove this question mark here it again is throwing us this error I need to put also data and if I put an exclamation Mark here because by this point of my application I know that the ID is always here and it's always defined so if you head over to my application and if I click on any delete button after a few seconds you see that to-do got deleted like this and after that you see that my list is going to be updated as soon the as soon as the operation is done another thing that you can use here for example imagine that you need to do something after that this mutation is done how to do it how to know that this mutation is done and how to do something after this mutation is done inside this too's component here we are using the not async mode of the mutation function if you want to use the async mode of mutation we simply need to put async here before our function then I'm going to put a weight here and instead of using mutate here I'm going to use mutate async and after that if this operation is done then I can do something else for example I can log success here or for example I can directly change the estate of another component and so much more just keep this in mind both mutate async and mutate are valid another amazing feature of this library is that we can simply handle our patching pated data we can handle easily the pagination with this amazing Library so I need to create another component here for example for example I have a list of projects that they're paginated and in each page I have five 10 or even 15 projects create another file and react component like this projects. TSX I'm going to export default function which is called projects here and inside it I'm going to return projects to see everything is working now if I head over to the app. TSX file I'm going to put react fragment around it it here remove the semicolon comment it and below it I'm going to import the projects that I created earlier now if I head over to the projects file here I need a query that Returns the list of my projects how to do it if you head over to the API file then below it here export const get projects async and it's going to have an argument called page param or anything else doesn't matter which is of type page param is of type number here then I'm going to get the data for my projects like this A8 axis instance. getet which is of type project which I did not I didn't Define it yet get project is an array let's go to the types folder then create a file called project. TS here like this and my project isn't a fan isn't a fancy thing it's a simple interface which I'm going to export IT project it has an ID and a name of type A String then if we head over to our api. TS file I'm going to import it here like this then in my projects endpoint of my backend service which have as pagination by default I'm going to specify the page to page which I did a simple mistake here we do not need this page parm here for this type for this section of our tutorial I'm going to remove it we need to put page here and it is of type number but for Simplicity and for initialization I'm going to put one here because I want my page be one if there is no data available for my page and after that I'm going to put another argument for my API which is limit three it means that in each page we only will get three projects not more for Simplicity and after this I'm going to wrap this whole a weight here and after that I'm going to get the data directly from it then if we head over to our queries file here I'm going to create another hook function like this use projects which has an argument of page which is of type number it's going to return a use inside it we have gr key which is projects here or anything else and also the thing that is going to change here for this query is our page number because we have pagination so I'm going to put the page here like this and for my query function I'm going to to use this function that I created go to projects and I'm going to pass the page here like this the difference between this new query this paginated query and other queries that we just defined earlier is that we need to use the placeholder data field here like this I'm going to explain you what is it in a second then I'm going to import keep previous data from react query like this it's here so what is this placeholder data here imagine your user is at page one what happens when he wants to go to next page to second page the UI of the application would jump would flicker for a second for a small moment why this happens because the page key here has changed what this technique helps us to do is that while the next page page data is loading it will keep the previous page data until the new data is loaded and seamlessly will get replaced by all data and the user won't notice anything any gap between data transitions this happens so smoothly so if you head over to our projects component that we just created I'm going to initialize my page and set page state from the use a state Hook from react like this after that I'm going to use the hook that I just created there use projects and then I'm going to pass the page here don't forget to put one here because the initial page is one but for other apis for other points for other services it might be started from zero index I'm going to get data is pending error is error is placeholder data defined and is fetching is fetching then for the return of this function I'm going to put a div here remove this projects here if my query is in pending state if new page or even first page is loading I'm going to show a loading message here like this if there is an error here I'm going to put another message here like this error is equal to error. message otherwise I'm going to have my data like this if and I'm going to map over my data like this my data are my projects then this might be a project here I'm going to render a simple paragraph here don't forget to put the type project. ID why I don't get intelligence here the problem is that in my api. ts file I forgot to put a return here and the problem is solved and for the value inside this I'm going to put project. name here after that I show my user the Project's IDs I'm going to show him the current page like this current page which is a page number I'm going to create a simple button and on click of it I can go to next page like this set page I'm going to get the older previous state like this and I'm going to use JavaScript math Library like this and I'm going to get the max value between these two values minus one and then zero for the label of this button I'm going to put the previous page very simple I'm going to put a space here then I'm going to create another button and on click of it I'm going to put this function here if there is no place holder data I'm going to set page all plus one then I'm going to make my button disabled then I have placeholder data then I'm going to put the label next page for my button and after that I simply want to show the user that the query is running is fetching new data is fetching is true I'm going to return span loading otherwise I'm going to return nothing and another space in front of it and if you look at our application here we see that there is a problem here because instead of three projects it's loading 10 projects here I forgot to use an underline here if I refresh my page you can see I get first three projects if I hit on next you can see after delay of 500 milliseconds the new projects are loaded like this like this and like this but what happen if I go to the previous page you can see even if the create state is unloading a state in the background can see but the cash data will show us the EST stale data which is a pretty amazing user experience because the user won't see any flickering any jumps or any loading Estates between paginating the data the fetch data but as you can see the background the query is validating the correct data which is a exactly the behavior that we want that's it for pagination intense tack react query another feature of this library is making infinite scrolling implementation much easier I'm talking about the scroll type that you get for example on the Instagram or YouTube while scrolling down and while you are scrolling down the new data is going to fetch if you want to implement this without using this Library it's going to have so much boiler plate code and it's going to be very hard but with this Library this amazing feature is going to be done in a few lines of code so let's get it started go to your app TSX file comment this component then commend this import here then put a component here called products for example imagine that your user is scrolling down and he's going to see products and then he clicked on load more button or scrolled more is going to see more products which are getting fetched from server one by one so go to your components folder here then create a file called products. TSX then export default function products here then return and products here like this you see everything is working then go to app TSX file then import it here so head over to your api. TS file here create a function called export cons get products like this which is going to be of type async and it's going to get a Page param Field like this and it's going to be type of type page param then open up the curly braces here inside it I'm going to then I'm going to return and weit here like this a wait axus instance. git a list of products like this which I did not Define this type to I'm going to go to the types folder create a file called product. TS then it's also going to be of type the project that we defined earlier export interface product it's going to have an ID of number then a name of string two if you head over to our api. TS file I'm going to make it bigger import it here it's going to get the data from the products end point of my back end which you can download from the link in the description it's going to have the page of page parm + one and with the limit of three products per scroll then I'm going to put a simple bracket around this and then I'm going to get directly the data if you head over to the queries file here I can simply create the query hook like this use Pro products this time then inside it I'm going to return instead of use Query hook I'm going to return use infinite query hook which I can import it from here then inside this options object I'm going to put query key which I forgot to put the cly Braes here I'm going to put the query key here which will be going of type products here I'm going to use a product function like this I'm going to use the function that I just created get products initial page pattern it's pretty self-explanatory for getting next page param we have access to last page all pages then last page parm here in the call back function then in the cly says if last page. length is equal to zero I'm going to return undefined it means that there is no other Pages here otherwise I'm going to return last page param plus one for getting previous page pram or parameter here I have access to first page here all pages then first page param here inside this function I'm going to check if first page par is smaller or equal to one then early exit with the type of undefined here otherwise return first page param minus one and that's pretty much it for implementing the infinite scrolling for our query function we did not use these values here so we can put an underscore instead of them this error go to make this error disappear underscore here and underscore there I need to put another underscore here because we only need the third argument of this callback function if we head over to our products component here I'm going to initialize this product qu that we just defined with use product hook here then inside the return function I'm going to use product query. data. pages. map and this Pages do map is going to return another array in each iteration so we can map over those arrays also to do this I'm going to call this group and I also need to get the index of this map function then inside it again I'm going to again map over the group here then I'm going to call it then again inside this map here sorry I forgot to put it inside the react fragment here like this and because we need to pass the key here we need to use the react fragment fragment like this and put the key index here and again for this we need to use also and inside this we going to button here and I'm going to pass the product. name as a label of this button and on click of it I'm going to return the simple function when user clicks on this button I want to somehow save the ID of this product here because we're going to need it in the future so in the above of our component I'm going to create a simple State like this select it product product ID set select the product ID use State like this and it might be of type number or null and it's going to be null by default then inside this unclick function here I'm going to product ID like this set selected product ID to product. ID here I'm going to put a break here for better organization and then I'm going to use also another fragment here and I'm going to use the key of product. ID here below all these fragments I also want to add another break here I'm I'm going to open another div here and inside that div I'm going to put a button here which I'm going to call it based on my query function conditions products query do. is fetching next page is true it's going to return loading more otherwise is otherwise if product query that has next page is true I'm going to return load more for my button otherwise show nothing more to load then on the unclick of this button I'm going to put this product query. fetch next page which T query will provide us by default and I also want to disable this button while it's fetching or there is no other page product query. has next page or product query that is fetching next page like this but while I use this selected product ID here I just created it to show you another feature of react query which is getting queries conditionally or get queries based on previous queries for example here I want to get my complete to-do by its ID how to do it I'm going to put const product query instead of product query and I'm going to use see use product tool which I did not Define it yet again as before go to the API TS file create a function called get product here inside it use async like the other ones the ID is going to be off type number and inside it I'm going to return andate axos instance. getet is going to be of type product and is going to be get from the endpoint of products slash ID and I'm going to directly get the data here and that's it go to the queries file here below it I'm going toate create another simple query like this use product ID might be number or null why null because if you read if you head we to the products file here we Define the ID here number or null because initially there is no selected product so we have no IDE so again as before we're going to initialize the query sorry I use the error function wrong here and this equal is wrong here then I'm going to initialize query client use Query client like this I'm going to import it return return use Query here like this inside I'm going to put query key as of type product ID query function is going to be get product ID the intelligence of typ script is throwing us this error that number or null is not assignable to type null because the get product here is of type null but the ID here that we Define find maybe null or maybe number so how to solve this we yet don't know that this ID is number or no but we can make sure that our ID is defined by this if we put if we use enabled from usequery Hook like this and if we pass our ID here and make it a bullan value like this or for more Simplicity put double exclamation mark behind it so if there is an i here and our ID is defined it's going to return true otherwise it's going to return false and if this is true then the query is enabled and active then this function is going to run and by this point we know that our ID is always defined at this point so I'm going to put an exclamation mark here to tell typescript that we know that our ID is defined here here I want to show you a simple trick that you can increase the performance of your application by reducing unnecessary delay between loading requests so how to do it I'm going to use placeholder data field here I'm going to return a simple function I'm going to Define cached products here like this and it's going to be equal to query client. gquery data and I'm going to get the products here because if you recall before we getting this product product we're going to have this products query in our cache so while this product query is loading I can show you some part of that product from this products list because we have IDs because we have the ID of our product from the list of products or maybe we have another Fields like name price quantity and many more and while our product is loading we can show you the part of the product loaded by products as a placeholder it's not much that difficult to understand we're going to make our app faster just by tweaking a little bit of things so I know that this here is going to be of type as Pages product undefined then I'm going to wrap this Square client section here in parentheses then I'm going to put question mark pages is flat 2 to get correct cache data I'm going to remove this s from here because it's not necessary and import it like this so now if cached products are available and defined I'm going to return cached products. find item item. ID is equal to ID I'm going to return item from cach products where its ID is equal to the ID that I'm passing to this Hook from the component to this hook firstly I'm going to import it then I'm going to put this selected product here select the product ID here then below of our component I'm going to put a simple indicator that what is going to be shown if selected product product is going to be of type json. stringify product query. data as simple as it so if we head over to our application we can see firstly we have a load more button here if you click on it we can see more data is loading loading it's loading loading loading and when there's no data it's going to be show us this nothing more to load from here because we know that there is no data available and 10 stack query is smart enough to know that but why we put these products here as numbers because I wanted to show I wanted to show show you something just pay attention carefully if I click on this product 16 here if you recall that our API has an 500 millisecond delay but why this happen immediately you can see when I click on these I'm showing to user the whole product here so I can expect that each of these products get at least 500 milliseconds to get to be fetched but if you head over to to our use product here we see that we are getting this data here as a placeholder from our cache by query client. getquery data by this key which is our products key so this feature enables you to do many other things and opens many possibilities for you if I open up the dev tools here if I click on product one let me just make it a little bit bigger put it on the right side here refresh the page if you pay attention to this product here I'm going to click on this product as you would see the product was fetching because it was I'm going to click on another product here like this it's going to be in fetching mode but while it is loading you can see immediately product is shown here and this is another amazing feature of TAC query library because you have access to the cached queries and you can manipulate them whenever you want so that was it please don't forget to like And subscribe as it really helps my career on YouTube to continue by this point of video you have learned almost all of the concepts of TAC query Library we have talked about queries mutations invalidations cached queries placeholder data infinite scrolling paginated scrolling def tools and many more I hope you have enjoyed and learn something
Info
Channel: Code Genix
Views: 19,731
Rating: undefined out of 5
Keywords: tanstack query, react query, data fetching in react, redux substitute, mutation, cache invalidation, parallel queries, chained queries
Id: 3e-higRXoaM
Channel Id: undefined
Length: 78min 54sec (4734 seconds)
Published: Fri Dec 08 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.