All 12 useState & useEffect Mistakes Junior React Developers Still Make in 2024

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we'll talk about the top 12 mistakes that Junior react developers make when it comes to the use State and use effect hooks in react number 12. let's say we have a simple counter component here I have a simple button here on the page and it's showing us the count is Count when I click the button we have handle click and that's going to set the count to count plus one and it looks like this and it works as expected now what if you do this so I'm duplicating the line here because let's say we want to do it again right after this we want to do it again the expectation now is that it will increase by two when we click Let me refresh here for a clean slate I'm going to click we don't see an increase of 2 we actually see an increase of one still and no matter how many times I add this and refresh here if I click here you will see it does not increase by anything more than one every time I click it still increases by one and not by four as you would expect maybe because when you set the count this is basically scheduling a state update so in this line we're scheduling that sometimes in the future reacts will update the count so then when you go to the next line it's not like the account variable has already updated this one has been set scheduled and this one will also schedule some update in the future but still using that same count variable so if I first load the page here initially this is going to be zero and this will also be zero if we click on the button now this count is simply zero so it's going to be zero plus one and the result of that is one and it will be scheduled in the future so when we get to this line count is still zero it isn't one yet so it's still zero so this will also schedule the count to be one in the future when we get to this line counter still zero it hasn't been updated yet and the same for this so they're all gonna set counts to one so if I save here you can see if I click once the count is simply becoming one and therefore it doesn't become four as you would expect on the first click the solution here is to use the updater function version of updating the state so with you States you can also obtain like this with a function if you do it with a function you get the previous value as the argument you can use that previous value now instead of counts we can just say take the previous value and increment it by one this previous value is actually up to date so if you schedule something you basically can get access to the as here in the next line as long as you use that updater function so this is the most up-to-date value of that count variable so if we do it this way if I now save here and refresh the page now if I click you can see it increments to 4 if I click again it increases to 8 and it increases by 4 every time I click now some people have taken this lesson and think that you should always update the state with this updater function and that's not entirely true you can still open like this there's nothing inherently wrong with updating like this however in this case when you have multiple set counts you may want to use that updater function and in all other scenarios essentially you can still use this you'll see another example of this later in the video number 11 conditional rendering let's say we have some kind of product card and in the props we get the ID so this component is responsible for taking some ID and just rendering the relevant product card for that ID now it's possible of course that the ID doesn't get passed wherever it's used it doesn't pass the ID so in that case we could simply return no ID provided right so then you don't get to this part right because we already use the return keyword here so it returns out of the function right component is just a function and react as soon as you have to return keywords you stop there it doesn't continue to hear so here the only thing we're doing here is just returning a string no ID provider so that's what we see the problems here will start if you try using hooks after that if block so maybe we do use stains here and we'll just say something set something blah blah and maybe you want to do a use effect so I will talk more about use effects but you could do something like this we have to use statehook and the user fax hook and we got red squiggly lines that's number good so let's take a look react hook you state is called conditionally it needs to be caught in the exact same order every component render and we get the same problem with use effect here so the problem is that sometimes this ID may not exist and therefore we already return out of the function here however sometimes the ID may exist actually most of the time it does exist and then we actually do use use this and use effect here they will actually be invoked and that's not allowed in react so this implication of the hooks always needs to be the same in every render so you could simply do it like this simply do it after the hooks now I got an error here because I should import this so let me quickly do that I will import both of them now I'm using next.js here and these days we have clients and server components we'll talk more about that in this video as well essentially you cannot use use State and use effect in server components so I have to make this a client component and don't worry we'll talk more about this later so now you can see all the errors are gone and this still works now as a matter of style I don't like to have these two returns in my component function so I would refactor this a little bit differently so I would do it in one return here and I would do something like if no ID then I would say no ID providers and otherwise if there is an ID I would simply render the product card there right so I would prefer to do something like this so then we can get rid of this and this will work the exact same but I think it looks better to only have one return keyword number 10 incorrectly updating an object's state so sometimes you're going to have an object in your state so let's say we have this object here it has a name property City and age and there can be other things in this form let's say we just have one input for now and of course when we start typing here when I say Tim for example I want to actually update the state here to be that name so what you can say is on change so every time there is a change in that input field run the function handle change so let's quickly create that function here handle change so we have this event and here when we try to update the objects we may do a couple of things wrong here so we cannot just say something like user.name is e.target.value right so basically this is going to be Tim and we're going to assign that to user.name but this will not work so let me log the user here so we can actually see what it will be so I'm going to console log the user you can see when I save here we can ignore These Warnings it's just going to be an object with name empty still so now I'm going to type something and now you can see when I type we actually get errors so this doesn't work and you may think oh yeah of course because we actually need to return an object here and this is an object so let's make this an object an internet object we have a name and we should simply set that name to e.target.value right so whatever we put in the input field so if I save here and now if I try typing here let's see what we get and let me add Ctrl log again so I'm logging the user objects and Let me refresh here for a clean slate okay so you can see initially we have this objects and now if I start typing you can see we get an object again and it has the name correctly as well but then it doesn't have the city and age properties that's how our objects here should have name but also a CD and H and when you do it like this this is a common mistake you are not copying over the city and age properties so what you want to do here is you can take the user objects here that we have and you can just spread that out over here this will copy all of those properties including name into this new object that we're passing to set user but then we have this name after that so this will override that so if we do this and now let me refresh for clean slate this is the initial object and now if I start typing you can see our object has the same properties with the updated name so this is the correct way of updating one property in an object here we are using this View user variable here in practice you do see a lot of people use the updater function here it's not necessary but a lot of people seem to do it we can get the previous value of user instead of using user we can just use brief error I get some strange issue with typescripts here we can ignore that but this is also a common syntax when we do this you have to pay attention to how you're returning something here so here it's a function now so now when you have the first curly Branch that's not going to be the opening curly branch of an object this is going to be the opening curly brightness of the function block so here what you can do is you can wrap it in parentheses so then you don't have to use the return keywords so here everything in the parentheses that's what you will return so you can run it like this and the errors will disappear or you can actually write the return keyword here so then you would go into the function block itself and then have an actual return statement here and we would return an objects here with these things in there and so now looks a bit strange with all these curly braces and parentheses right so really make sure you've mastered JavaScript itself check out the JavaScript course in the link this is another way of doing the same thing number 9. let's say you have a form with a lot of inputs so we have first name last name email password in the real world you can have forms with dozens of inputs and we want to keep state of all of that so let's say we have first name here and now a beginner may say oh we also need one for last name and email and password basically create a separate state for all of them and that's not what we want to do it's cleaner to just use one object here for the whole form so you can have an object as state and then it would just be let's say form set form and then in the form you would have a key for each input so first name maybe empty initially last name email password address ZIP code right so just use one big object for all of that now if you want to update this it's actually very easy you can just use one function so if I want to type here and this first name should get updated we've seen that you can use on change we want to run a function called handle change which we're going to Define here and we'll change all right and then we can just update that so we can say set form and we've seen how this works now right so now we want to update one property in an object so it should be an object that we have here we can spread the form here so we get all the contents of that form here and then we can overwrite something so here we want to override first name with whatever we put here and then we can get that from e.targets.value right so now this first name will get properly updated here in the form in practice you're gonna see this updater function format as well for this so here when you want to return something you do need to wrap it in parentheses or you need to use that return keyword like we saw before and then we can use previous instead of the form right so this is pretty common to see so now we have a dance we're setting a new object here we copy everything over from the form first and then we override the first name in this case and that's only the first name what if I type something from my last name here what we want to be able to do is just copy this for all the other ones as well and we can actually do that this is the best way to do this so now I added this to last name if I type here it's going to fire this function is going to set the first name here that's not what we want it should become last name so how do we solve this well these inputs they also have a name attribute so here the name is first name name is last name name is email name is passwords these names are the exact same as what we have in the objects for the keys here so what we can use is actually instead of hard coding first name here there is something else that we got in this event variable which is either target.name and we can use that for the object key here that we want to override and you can actually write this in JavaScript like this so you have square brackets and then you can just use e.target.name right so if I type here we're going to run the handle change function well this one has a name or first name so this will simply become first name and it will get the value that I type here and now if I type here the second one with last name as a name this one simply becomes last name with the value that I type here so that will properly update this part right so now we can simply use this handle change for all of the inputs here right so I can added to all of them like this right and if you want to use the updated function here it works the exact same you just make this a function and now the opening curly brace with functions is going to be like the opening of The Block so we need to wrap this in parentheses if we want to return this or we actually want to go in here and use the return keyword like we saw before right and then you would use previous to spread the previous value here and then override it like this but I prefer this syntax we don't need the previous value here all right number is let's say we have some kind of cart and this card is keeping track of the quantity and every time I click this button we run the function handle click which just increases the quantity by one right very straightforward now let's say we want to show the total price here as well so we need to keep track of the total price here so a beginner may think oh I'm gonna type I'm going to write a new state here so total price set total price and maybe we can say something like initially zero and then every time we update the quantity we want to update the total Prime so you may think I'll use a user facts right so here we can say use effects we want to to run this function every time the quantity changes so you have a dependency array and every time this quantity variable changes we want to run this function in that function we can set the total price to well what is going to be the dollar price well that's always quantity times the price per item so now what we have is every time I click here we run this function and it will update the quantity which means that this user fact now will also run and it will set the total price but it makes sense logically when you think about it like that and now we can just output this on the page the total price is going to be something so now we have one initially and this will also run initially so it's going to be 1 times 5 is 5. if I click again it's gonna add another five right because quantity obtains quantity becomes 2 and 2 times 5 is 10. every time a click it increases by five alright so this is very bloated and this is not necessary at all so here if we want to know the total price we don't need to use u stand or use effects right we can just remove that so I'll comment this out because we can derive it from the quantity and Enterprise per item so here you can just create a variable in your function body there's no you can do that and you can say the total price this is going to be a variable total price and that's going to be the quantity times the price per item right you can do this of course if I save here and start from a clean slate if I now click it still works the exact same because what happens is initially when it first renders this components it will go in the function body here line by line the quantity will be one it's going to do one times price and which we have set as five so then here total price is five then if I click handle click this function will run it will update the quantity which will re-render this component so we will go into the function body again this time quantity will be 2 because we added one and then we run this line again this statement should will be 2 times the price per item which is 10. so now total price is 10 and it will be output on the page right so you can see that you don't need all these hooks every time if you can derive it or calculate it from already existing States you don't need to create new state and use use effects another typical example of this is for example if you have the first name of somebody right so we have first name and then maybe also keeping track of the last name right and now you want to know the full name so you think oh well full name well we're just going to create a new you state for that and for full name and that's not necessary we can derive it from already existing States right so you can say full name well not simply the first name plus the last name right no State no use effect needed every time one of these updates the function will re-render it will go statement by statement again so every time the full name will get updated as well right so very typical Junior developer mistake all right number seven Primitives versus non-primitive values let's say we have a price component and we just have a simple button here and when we click the button we run a function called handle click which we have defined here and the only thing it does is set the price to zero every time right so initially it's zero and this one is also gonna set the price to zero now you probably learned that if the state doesn't change the component doesn't re-render rendering a component just means in the function body we just run all the statements again so we just run the entire thing again so let's do that's actually true let's just log something at the start of the components here component rendering so we're going to lock this and I'm going to open up the dev tools console here I'm going to clear everything here so now if I click this button let's see what happens so now if I load the page and this component first mounts we see component rendering right so when it first mounts it's going to run all the statements in the function body here so we indeed log this now if I click again and I keep clicking you can see it doesn't say component rendering again because here it can see that this is the same value as it already is right so it won't re-render the component and that is true if you have a number or a string so now if I try to set it to a string called test now I'm keeping the state a string called test restart here from clean slide now if I click again you can see it doesn't re-render same with a Boolean so if I set it to true and I set the price to True whenever I click the button let me restart again now I'm going to click here you can see now re-rendering however what if we actually have an object here this may actually describe the price so it may have a number for the price let's say 100 and it may also have some kind of Boolean in there so total total price true right so now the price variable here is an object with these two properties and what happens if we set the price to an object with the exact same properties and values so I'm going to copy this I'm going to save here and refresh here for a clean slate so now what happens is whenever I click you can see the component re-renders why is that because you think when you look at this officially speaking it looks the exact same but I didn't make a typo or anything right it's the exact same state you would say and why is it re-rendering well that's because in JavaScript there are primitive values that we just saw that are passed by value and the objects and arrays are passed by reference so if I have a variable a that's the number five let's say and I have a variable B that is also the number five if I say a is strictly equal to B JavaScript tells me that's true if I have a variable called C with the string test and a variable D with the string test if I say C is straight to equal to D JavaScript will tell me that's true however what if we now have an object so let's say I have an object Y and I have a key of hello is one let's say so this is an object and now I also have another object which also has hello is one and it's the exact same right you would say so now I'm gonna write Y is strictly equal to Z and JavaScript is telling me that's false because in JavaScript whenever you write an object literal like this you're not actually working with the object itself you're working with a reference a pointer and this is a bit tricky to understand but what you need to know is that this is not the actual value that you're working with you're working with an address and the address for this object is going to be different from the address of this object so an object is more like a box in the real world you can have one box with the exact same contents as another box but there are two different boxes right an object may have the exact same contents as another object as the exact same contents here but there's still two different objects and that's not true with strings and numbers and Boolean so they are always the exact same you actually work with their actual value here you work with their reference so here what happens is we have this object here and when we click we're setting it to this object and this is a different object right and reacts will see oh you're passing something new here this is different from what we had before because it's a different object and therefore react will say well it's different so we're going to re-render that's why when I click here it keeps re-rendering in practice this is mostly dangerous for when you have some kind of dependency array most commonly with use effects the way it works is you're going to run this function every time what you specify here in the dependency array so if you have it empty it's just gonna run only once when it first mounts but you can also specify a variable here like price and now every time price changes this function will run as well now you want to be careful with this because this object is going to change every time you update it so typically you don't want to depend on an object you want to depend on a primitive value like a number Boolean string so you can also just look at the contents of the objects so you can say price at number number so now you're just depending on a primitive which will prevent this use effect function from unnecessarily running number six initializing state with an object so let's say we have some kind of blog post component and here we have the post and we can set the post and here we have a use effect so use effect the way it works is we have this function here and with the dependency array we determine when it should run so an empty dependency array means it's only going to run when it first mounts when the component mounts it's going to fetch the past eventually it gets a response it will parse that response as Json meaning it will convert it from Json to a normal JavaScript object so we can work with that that's going to be data here and that's what we're going to set the post as and this can take some time can take multiple seconds but here we are already rendering post the title post.body so if I save here let's actually see what we get so here you can see again an error because initially it says something but cannot read properties of undefined so we have post.title but poster title is undefined because I haven't specified an initial value here right so initially post is going to be undefined so here immediately you're going to try to undefined that title and that's not possible you're going to get an error and also remember use effects runs after rendering so first you try to render this on the page and then after that use effect round and so make sure you've mastered the reacts fundamentals check out my react next to escorts so while we're waiting for this to finish and we actually have to post data we are already trying to access post.title so post this initially undefined and if you try to access something on undefined in JavaScript you're going to get this error so one way around this is to use optional chaining so we're basically saying post may not exist it may be undefined so if we try to access something don't throw an error so if I save here we don't get an error and now we actually get the data as well now typically people initialize this not with undefined or leaving it empty it's better to make it explicit that it's initially null and in JavaScript if you want to Mark something explicitly as not existing you use null undefined is more accidentally not existing essentially no is when you are really deliberate about it so here we are deliberate initially it's empty right so 40 the empty State initially it should be null so initially it's going to be null and then we can try accessing title and body and it works the same way here so if I remove this initially we're going to get an error because title you cannot access that title or no so we could do this optional chainings thing we could do this but a cleaner solution is to use some kind of loading state so what we want to do is simply not render anything until we actually have the data from the post right that makes much more sense so what we can do here is we can have something like loading if it's true we may just want to say nothing or maybe loading dot dot and otherwise if it's not loading we actually want to display this title and body here we do actually want to display in the title and body so I'm going to put this in a react fragment because I don't want to clutter up the markup with divs or anything we don't need a div okay so then we have loading and then we can just have a state for loading so we can check if it's still loading so we can say loading initially is true right and then here it starts fetching this and eventually it has received data and we can set loading set loading to false that so we can do this so now let's see what we got if I save here the error should disappear we get a loading State and then we get the nice post right so this is a much cleaner solution now you don't really want to fetch yourself in use effects and we'll talk more about this later in the video so keep watching number five a very typical typescript mistake and react you don't have to understand typescript right now this will be a good introduction so you can see my file now is called dot TSX previously I had jsx this is plain JavaScript and TSX you can use typescript now when you do that and we take the previous example remember we had this post initially the post is no so post is going to be null and here in rendering we also have loading state so here if it's loading we just want to render loading and then here we're fetching the data when the component first mounts it's an empty array so only once when it first mounts it will fetch the post and eventually when we get the response we set the post to the data and we also set loading to files so here when loading is false the post has been fetched and we want to display the title and body now previously we didn't get any rats quickly lines but now that I enable typescript we see these rats quickly lines so touchscreen is giving us a warning here essentially and it's saying post is of type null and that's because with typescripts in react if you're using State here typescript can infer what the type of this variable is going to be so for loading here for example if I hover loading typescript is telling me loading is going to be of type Boolean how does it know that I have not specified this myself I could specify it myself and the way you would specify it is with this weird looking angled brackets you could say this loading State let me make this wider this loading state is going to be of type Boolean so we're going to see loading as Boolean but typescript could already infer that so we don't need to do that and so typescript can infer from the initial value that you pass in what type it's going to be so if you have text here for example initially that may be a string now I could specify string here I could tell typescript hey this variable here text is going to be of type string but I don't need to do that because typescript can see this oh this is going to be a string so if I hover this you you can see it has already been inferred as a string by the way what's the benefit of this okay so typescript knows that text is going to be a string so what if typescript has the correct type here for its string typescript can then help us out so here let's say in the rendering here I'm trying to do something with text so I can try to upper case I can try to replicate it and typescript will not give me a warning because it knows that two uppercase is indeed a method that you can use on a string however if I try doing this on loading the loading variable which is a Boolean right touchgrid has inferred this to be a Boolean if I try to do something like two uppercase touchgrip will tell us that this two uppercase does not exist on this type right so touchgrip will help us out if we or somebody on our team makes a mistake and also when we try setting the state here let's say set loading if I try to make this for example a string files Tasker will help us out it will say well you cannot assign a string because this loading is supposed to be a Boolean right so here we're trying to assign a string here right string happens to be false by correctly typing things we get these guard rails from touchscreen and the same with count for example so these are all primitive values that maybe count initially is the number 100. I could specify this count is going to be of type number but I don't need to if I leave this now typescript can look at the initial value and see how this is going to be of type number right so here count is going to be of type number touches can automatically infer that when you use a primitive value like a Boolean string or number that's not the case when you have these objects so here with objects initially we want to have null but later we know that it's not going to be null we're actually going to set it to some data and this is quite common when you have some fetching in your component so how do we type this then because initially it's going to be null so if I hover post now you can see typescript has inferred this to be of type null and if it's of type null you cannot access title and Body on post and now we actually do need to specify what type it's going to be so we have these built-in types like string and number and Boolean but we can also create our own type so we can say eventually this is going to be of type post right so now we need create a type so we have type and we can call that post we can say that's going to be an object so we have curly branches it's going to be an object and let's see it's going to have a title and body so we say the time there's going to be a title and that's going to be of type string it's also going to be a body and that's also going to be of type string and you could have other things here maybe this post has tags for example and maybe it's an array of strings so we can have string and then you can have the array symbol and now you're saying these tags are going to be an array of strings right and we have number Boolean Etc so now we're telling typescript this post variable is going to be of type post and now it knows it's going to be of type post and post has subtitle and body so now we can safely access title and body you can see we are we don't have red squiggly lines anymore but now we got red squiggly lines here under null so what's going on here well this is because we are telling taskgrave this post is going to be of this type but now what we're passing in is no so not saying hey you told me that it's gonna it's gonna be an object with title and body but what you're giving me here is null and that's simply because it's the initial value so typically what you want to do here is you can say it's going to be of type post or no so it could be null here initially but eventually it's going to be a type post and so touch screen looks a bit strange we have these angled brackets and this looks a bit confusing we talk a lot about typescript in my react and next to S course as well right so don't worry if you're not completely comfortable with this I will just use this from now on so you can learn a little bit about it number four not using custom hooks so Junior react developers seem to be a little bit confused or scared to use custom hooks so as an example I just have one component here and I have another component here right you can have multiple components in the same file that's not a problem all right now let's say that this component needs to know the width of the window so it could create a state for that window size set window size and maybe initially it's going to be 1920 and let me import this and we're using U stays here so I need to make this a client component we'll talk about that in a second and this stays here for Windows size we're going to keep track of that in use effects so use effect we want to run this function but only initially when the component first mounts and let me import with this and in this function we're simply going to attach an event listener to the window object so whenever it resizes we want to update the state so it's going to be this function that we want to attach so here this function will run every time there is a resize event now we'll talk more about this but these use effects they also have a so-called cleanup function because when this component unmounts for example maybe we're navigating away and this component should not be visible anymore this event listener is still attached to the window and we want to remove that when this component is not being used so in react you can also return a function here so this function will run when you unmount your component and in this function we can simply remove this event listener right so it's a cleanup function basically we need to clean up our mess basically before we completely remove this components it's also important to know the inner details of how all of this works the important Point here is that this is actually a quite common scenario you have some states and you update it in use effects and this is a lot of code now very commonly other components will want the same information so let's say this example component 2 also wants this code so a Eve react developer Junior react developer would simply duplicate all of tests they would also put all of this code in those other components so now we're going to bloat up all our other components that need access to that as well very duplicative code now now if you've learned JavaScript properly you may have heard of the dry principle don't repeat yourself so whenever you have some kind of repetition it's a good candidate for refactoring it into something that's a little bit more reusable and that's the same when you use hooks in react so here we can create a custom hook out of this and it sounds very fancy but it's just refactoring this into a separate sort of utility function or helper function essentially so let's see how we can do that so we can simply create that right here so we can just create a function now typically the name of these start with the word use to indicate that it will have reactor hooks in it and use window size let's say you can give it any name you want but this makes the most sense I think and then we're just going to put all of these cows in there so we're going to remove it from this component we're going to refactor it into one function here now we can remove it from this component and we can also remove it from desk components and no need to duplicate ourselves we're just going to refactor it into one function just like it would do otherwise in JavaScript if you have some kind of repetition it's the same in react the only difference is basically that you add the word use in front of it because you're using use State and use effect in there so this helps indicate that you're using these react features under the hood right and then you can just use that here so you can say use window size you can just call that function and it will basically run as the exact same as what we had before but I can add it here as well right so now this is much cleaner looking in the components now in the components we wanted access to the window size so now we do need to return the window size from this function so let's return window size and then we can just grab that here when we invoke it Windows size so this would be the complete example so here I would also add that so now we get access to the window size in these components but the code has been refactored into one function that we can reuse so that we don't load up our component with repetitive code right so don't be afraid to create custom hooks we talk a lot about this in my react next.js course as well number three these days we have server and client components in react if you're using next.js you may have already seen them if you're using feed or create reactor app you may have not seen them yet but this is basically the future of react so we need to know a little bit about how it works in relation to these hooks so I'm using nextges and specifically I'm using the app directory in next.js and by default your components are server components and that means they're only going to run on the server now on the server they will not keep track of state so if you try using use State here if I try doing this and even if I import it here if I save here I get an error basically I cannot use this in a server component I need to convert this into a client component I can do that by adding use client at the top now before I do that let me show you some other things that also don't work so use effect also doesn't work so this is a sort of a life cycle hook and you cannot do that on the server right so user fact will not work even if I import this right so here we get the same error so the other hooks in react also don't work here another thing that doesn't work is for example if if you do anything with the window objects so for example alerting does not work on the server right so on the server we don't have access to that window object so here we're going to get something like Windows not defined because there is no window on the server this has nothing to do with hooks but I just want to show you this also for example local storage right if we try to do some get item local storage does not exist on the server it only exists in the browser same from the window that's a browser feature the browser gives that to us so this is not going to be available on the server it's not going to be defined so whenever you need access to these client-side features you need to make this a client component there are two ways of doing that you can add use client at the top or not use this but you can import it into another component that is already a client component for example if another component has use client at the Top If you import into that other component this will automatically also become a client component so you can imagine a tree of components in react as soon as you add use client to some component all the other components that you imported there will also become clients components so this is basically like a boundary in your react 3. from now on everything here becomes a client component this is also something that we talk much more about in my react next to S course number two still closure so let's say we have some kind of counter component and it's just showing us count as count and we're keeping track of the count in this new state so far so good now let's say that every one second we want to increment this count by one so we can set up a set interval when this component first mounts so that's a life cycle thing so we can use use effects so we can say we want to run this function but only when this component first mounts input this so this function will run when the component first mounts and in there we want to set up an interfall as it calls in JavaScript so what we can do is we can say set interval and here we can say run this function every one second right so the first time this component mounts we're gonna set up this interval that will make this function run every one second right so what do we want to do in there well maybe we just want to log into file function running and of course we we want to do is we want to set the count to count plus one all right so let's save here and see what we get so now we can see that the number has increased to one but it stays there why doesn't it keep increasing it should increase every one second let's check if we can see the console log in the console tab I have a refresh here we start from scratch and we can see that the interval function is actually running you can see here that this interval function keeps going so every second this function is indeed running right so this function is actually running every second because we can see that this log well we can see this every second it doesn't need lock that right so if you keep blocking the same thing in the console tab the browser will just increment this it's not going to put everything here right but the count for some reason stays at one how is this possible this has to do with a closure in JavaScript so here initially count is zero the first time we Mount this component count is zero and then we're gonna run the use effect so this function this whole function will run once when the component mounts and then we're gonna run user fact and in the use effect we are setting up this interval function so basically this function will run every one second but JavaScript will not recreate the function every one second so it will just create this function once and then it will just execute that function every one second and in JavaScript these variables if you use a variable like count those are created at function creation time and at the time of creating this function count is zero right so this function is only created once and then it's just executed every one second you can see here that in set counts if you make the addition here it becomes one so this is created one time and then it's just doing set count is one every single time that's why you can see that interval function running well we can see that right so this confirms to us that it is actually running every one second but set count is just going to be one all the time so yeah it's just gonna stick there right and this is a very tricky mistake that some Junior reacts developers make right so this is called closure this variable is getting the value at function creation time and that's going to be zero simply so how do we make sure that this updated so that every one second it gets access to the new value well we need to make sure that every one second that function is actually destroyed and then recreated again so that in the new creation of that function it can simply get the new value well maybe we can add count to this array right so you could say we should just add count to this dependency array now use effects will run not only when we Mount the components but also whenever discount variable changes so initially it's going to set this to zero plus one right which means that count will change count will be one count has changed so now we're going to recreate this function and count will be one one plus one is two right so then it should work so let's save here and see what we get I'm going to refresh for clean slate so now we can see 0 1 2 3 or and it was a weird Hiccup and there we have some more hiccups and now it's getting really strange and now we get a really strange result here where it's sort of passing out this simply doesn't work and the reason is that we are not canceling the previous intervals right so now whenever account changes we're simply adding another interval right so now every one second we're just adding another intervals this is going to go completely wrong yeah so you can see it's completely out of whack now so what we need to do is not only create a new interfall we also need to cancel the previous one so set interfall actually returns an identifier we can call it identifier which is I and we can use that to cancel this one so we use effects also has a so-called cleanup function so you can return a function here and this function will run when you unmount the component well that's not the case here but it also runs before running the next use effect call so basically you can clean up something from the previous use effect run so what we can do here is we can cancel that interval from the previous run we can call clear interfall and we pass the identifier like this if I save here and we go back refresh now let's see if we get a normal result which we want two three four five six and this seems to work right we don't get any strange effects here right so this looks very tricky we have this inner functions so it's really important that you have mastered the JavaScript fundamentals right so I see a lot of people jump into reacts with a lot of enthusiasm but make sure you've mastered like JavaScript and also CSS now there is actually a cleaner solution than this so we don't need to do all of this so let me remove this we can remove all of this again also on this so we can actually just create this function once it will work but we have to do the set function a little bit differently here so here we need to depend on the previous value right so what we can also do is simply do this so whatever the previous value is just increment that by one right and this will always be the most up-to-date value that we can get for setting state so if we try this and then our refresh here let's see if this works so now we create this function once and now you can see it is properly updating the count on the page all right number one has to do with fetching and use effects we saw it before but let's talk a little bit more about why you shouldn't do that in the real world so as an example I have a simple post component here and it's just showing us a button and it's keeping track of an ID and currently it's set to 1 and then it's also render during this post body component so I have another component here where it's using new state for text and it's going to Output that text and then we have a use effect here which is currently empty so we have two components here in one file that's perfectly fine and what we want to do here is this ID we want to pass that to the post body and based on that ID the post body will fetch some post let's pass the ID to post body here so we can do ID as ID and we get a touchscreen problem right so typescript is helping us out it's telling us that this component right now is not accepting an ID prop and it's true so let's actually accept an ID prop and don't worry you don't need no time script for this but if you have props for a component you you do want to type this usually so we can do that in line so we could do ID it's going to be number but I always think that this looks a bit clumsy I like to extract this into its own separate type post body props and let me Define that up here so type post body props it's going to be an object with an ID that's going to be a number so that's the ID and and based on that ID we want to fetch a post and display it here right so Junior developers do this is quite typical is when you mount a component you want to fetch some data and this is the fetch call that we want to make we're going to make a fetch call to some dummy API based on the ID so initially ID is one right so it's going to be post one we get some response we're going to parse that as Json meaning we're going to get Json as a response and convert that to a normal JavaScript objects and that's what we get here and then we can just set the text that we actually want to display eventually right so bear with me here so what we're going to do is whenever we click this button we want to be able to change the ID and then it's going to fetch a new post right so here show me a different post so let's do that now right so when I say here what happens is this post body will be mounted right so it's going to run once because this dependency array is empty so it's going to run once on mounting it's going to fetch that based on the ID the ID right now is one right so we get some post here post text okay so now we want to click on this button and it should change the ID so on click I could call it handle click can Define that up here but this time I'll do it in line here so here we want to set the ID but not to some fixed number like this it should be a random number so in JavaScript you can say math.random to get a random number between 0 and 1 and we want to do that times 100 so we get a random number between 0 and 100 and this can contain decimals so we're going to round it up or down doesn't really matter you can do math plus floor to round it down so that we don't have any decimals so 4.5 will become 4 3.2 becomes 3. right so that's not really important the idea here is that we're just changing the ID to some random number so now I'm going to click here and what should happen is that it should fetch a new post so if I click here let's see it doesn't work because right now the way that we've done this is user fact this will only run when the component first mounts because it's an empty dependency array so here if the ID changes transfer here if the ID becomes 10 let's say ID becomes 10. this component will re-render but this use effect will not run again because it only run when it's mounted we can add ID here so now it will run both when it's mounted but also every time the ID changes so now if I save here now if I click here you can see every time we get a new post that takes a second or so so I click now and you can see it takes a second or so before we actually get the post alright so so far so good all of this is fine if you're just testing something or you're building some very small app now in the real world though if we want to make it more professional we need to think about the edge cases as well for example what if I click multiple times quickly after another here you can see when I click multiple times it sort of goes through then flashes through them if I click three times here you can see it flashes through them if I click five times here it flashes through all of them because what happens is every time you click the ID gets changed and it's going to fire a fetch call so if you click five times and so we're gonna get five times so it's gonna make this fat call for all of them eventually they get some data and they're gonna try to set the text so you're gonna get five set text very quickly one after another and that's not really the UI experience that we would expect here if you click multiple times after another we don't want to flash through them we only want to see the last click basically the last one so we basically want to cancel previous fetch calls this is the real world right so if you want to become a professional developer these are the things that you're going to have to think about and solve so browsers do give us the option to do this ourselves so what you can have is a so-called new abort controller so you have a new abort controller and you can pass a second argument here to fetch it's going to be an object and you can pass a signal here and that's coming from the controller so controller.signal so basically we're attaching some signal to this Fetch and then we can use that to cancel it so user thanks also has a cleanup function this function runs whenever you unmount the components which will not happen here but it also runs before you go for another round of the use effect so it allows you to clean up some stuff from the previous run and that's what we can use here so what we can do here I don't have to go in here I can also just write it like this I can use that controller Dot abort so now every time this ID changes and we're going to run this user effect again right before we do that we're first going to run this cleanup function which allows us to abort the previous fetch call looks very clumsy as you can see but now when I do this and I click multiple times you can see when I stop clicking it will just show me the last one it doesn't flash through them so if I click twice it's only going to show one if I click three times it's only going to show one right so what we saw here if I remove all of this what we see here is basically sort of a race condition where the different fetches are basically racing against each other to see which one will set the text first or last and that's one problem that you're going to have with fetching and use effects but there are other problems as well like caching for example what if the ID is the same as one that you already fetched before you're gonna make another fetch call necessarily you could cache that and you can reuse the previous result and if you had some kind of caching solution we cannot do that like this here also it only fetches I have the rendering first we're going to run all of this I'm just gonna render this and then it's gonna fire use effects which will then change the text here and it's going to render again right so it's basic it's quite late basically before it can start fetching also what if you want to do some loading State we would have to create a new variable here loading set loading and then sort of undo that here set loading to files if you have an error with fetching you would have an error State and you know you have to keep track of that so if you shouldn't do it in use effect then how should you fetch data well these days in next.js you should try fetching data in server component so highly recommend you check out my react next.js course in which we talk about that and if you want to fetch data on the clients and clients components there are libraries like react query or SWR by for cell next to us that will take care of a lot of those issues like caching race conditions loading States error States and many other things that you will run into in the real world when you start fetching data right so I highly recommend you check out my react next to S course to really become a professional react next to S developer well done for making it this far this wasn't easy the version tricky things it's okay if you're a little bit confused but I hope that you learned a thing or two all of this is going to be very easy if you've picked up the fundamentals so make sure you master react and react is very easy to master if you have already mastered JavaScript and also make sure that you learn CSS properly I have courses and all of that check out the links in the description hope that you learned a thing or two thanks for watching and I hope to see you soon bye
Info
Channel: ByteGrad
Views: 759,955
Rating: undefined out of 5
Keywords:
Id: -yIsQPp31L0
Channel Id: undefined
Length: 46min 15sec (2775 seconds)
Published: Mon Aug 21 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.