React State Management – Intermediate JavaScript Course

freeCodeCamp.org · Beginner ·🌐 Frontend Engineering ·3y ago

Key Takeaways

This video tutorial covers React state management, including native state management, indirect state managers, and direct state managers, using tools like React, React Query, and Redux.

Full Transcript

in this intermediate react course about react State Management Jack Harrington will teach you about hook State context using request libraries for State Management Redux and more hi I'm Jack Harrington I'm a principal full stack software engineer and I am super excited to be here on free code Camp talking about my favorite topic which is react State Management the first thing I want to answer about react State Management is what is State Management so State Management is basically half of your react app when you think about it you've got the presentation side of the house that's the HTML and how you format it and then there is the data that's in your application the state and to me State and State Management is the Beating Heart of a react app and why do I say that well it actually is the only time a react app will re-render is when State changes when you add an item to a cart when you remove an item from a cart that's the time when the react app re-renders and so state is the engine that moves your react app in fact I would go so far as to say that reacts whole job is to turn State into HTML at least in the web context so in this video I'm going to give you a complete overview of all of the different ways that you can manage state in your rant application and that's going to start off with reacts native State Management this is the hooks we've all come to know and love things like use State use reducer use memo and use effect we are going to drill in deep on these Hooks and make sure that we really understand them because they are the foundation upon which all of the other State Management models are built in the second section we're going to talk about indirect State managers these are third-party libraries like react query react location react router it's not their primary job to manage state but react query for example it goes off in a queries data from the server and it gets it back and now it holds that data which is in effect managing that state and perhaps the combination of native Hooks and one of these third-party libraries like react query or react location is enough for your state management needs for your application and then in the third section of the video we're going to talk about direct State managers these are third-party libraries whose sole function is to manage state things like Redux Joe Tai valshio and sushdan and we'll talk about the different models and which one you might want to select for your application and then at the end we'll talk about some new things that are coming with some react rfcs that are just coming out in xjs13 that change the way that we think about how we might want to manage state in our application and I'll sum up by giving you some recommendations about what I suggest you might think about in terms of choosing State Management Technologies for your app but it all starts with getting to know react hooks really well so let's get right into it so we're going to start off by taking a look at Native State Management in react and in particular concentrating on the use State hook so to do that I'm going to build a Veet application I'll do that using yarn create Veet then you give the name of the application that you want so I'm just going to use native use date and now V which is a awesome way to create web applications can take multiple templates I'm going to use the template for react right now I'm going to bring that up in vs code all right so here we have our application I'm going to bring up the console and then we do yarn to install all the dependencies and then yarn Dev to start it up and I'll click on this link and there you go awesome here is our application it's even got a little bit of interactivity a little state in this case but we're just going to remove everything that we see here to start so where is that located well that's located over nap.jsx and I'm going to remove pretty much all of this but we'll keep around you state because we know we're going to need it okay so the first thing we want to do is experiment with using a numeric State a number and actually a counter is the best way to do that so we're going to basically re-implement this from scratch now all of this code is available to you on GitHub for free in the link in the description down below but you can just follow along me if you please so okay so here's we're gonna do we're gonna Define that we have some State associated with this component so to do that we say you state and we'll start our counter off at a given number so let's start with 10. now the output of U state is an array so let's go and get that array and within that array the first item is the current value of that piece of state so we'll call that count and then the second item is a Setter function you call that function to set that piece of state so call that set count now let's create a button that has the count and let's take a look see what it looks like all right so we've got a button down here kind of hard to see a little bit but it's got 10 on it but it doesn't do anything yet so we want to create an on click so how do we do that we'll use on click and then we give it a function so we're going to say add one is our function and then we'll Define that function so here's a mistake that I've seen people do I've seen people do count plus plus I think the idea is that well count is just a count and when I set it it should be retained so let's try that out let's see if that actually works Okay click on that nothing happens and so why is that well we're seeing that we're getting this assignment to a constant variable now what's outputting that is actually console ninja you want to go grab that that's from the folks at wallaby it's a link to that also in the description down below it's free and it's super handy like this so well okay we get it this is defined as a const right so let's go and redefine that as a let and maybe that will work all right let's give it a try now click still doesn't work but we don't get an error interesting okay so why is this well learning why this is is really critical to understanding pretty much all of State Management in react so I want to spend a bit of time on it and one of the things I want to do is I want to use a workbook to show how this is actually working so I'm going to create in us another extension called quokka a worksheet and what I'm going to do is I'm going to create a function that returns a value kind of like you state so call that function get state and let's say that it has some value in it say 42. and then when you call again state it just returns that value now down here I'm going to call get state now currently it just returns 42 but I'm going to go store that somewhere so I need to store that in a new value so like my value and we'll just ask quokka what my value is 42. and now if I set it to something else now my value is 22. cool but what happens when I go and get the state again so I'll say my value again and now my value again is still 42 because setting the value of a return just sets your local copy so scalars and that includes strings numbers and booleans so a number in this case are returned and passed by value where arrays and objects are passed and returned by reference and there's a huge difference there so when you're returned something by value you don't get it you get a copy of it which is not the same thing now you could say oh Jack you know you got it all wrong this is returning an array okay fine let's go try the same thing with array there you go so we see that again my value is 42 we set the local copy to 22 and then we again set that and there's no difference same sort of thing down here all right all we're doing is just destructuring a scalar within an array now there actually is a way to kind of make get state do this and that's the beauty of JavaScript enclosures but when you hack around that much you're not actually representing how react is actually managing State and the proof is in the pudding the proof is in this doesn't work so what works is to use that set count function that's given to us to set that count to be the count plus one or whatever you want so let's go over here and try it again and now it works perfectly so now I mentioned the count is associated with this particular instance of this component but this component is the app right so we only have one so what if we were to have multiple ones of these let's go and take app and just rename it counter and then we'll make a new app it'll just make a bunch of counters and see how that works now we have one counter down here let's go make a bunch cool now we've got four count buttons and now we can click on each one of them and they all independently set and that's what I mean by the state being coupled with the instance of that component each one of these components these counter components maintains its own count and thus going back over here we can go in independently mutate each one of these and they'll maintain their states individually so we talked about how to manage a scalar a simple scalar using use date let's talk about how to manage an array so we do that a lot as well so I'm going to create an array of names and then we're going to have an ability to add a name to that so let's get rid of one all these counters and I'll create a new function which is a component called name list so let's create some state to hold that list of names Jack Jill and John in fact actually let's go fix this to be const again so that's good okay good and now we're going to render that state nice and let's go and actually put it into our app all right good looking list there all right so we want to be able to add an item to that array so we need an input field so that's another thing you can do you can have multiple pieces of State associated with the same component so we're just going to have another piece of State called name which is a scalar string and then we need an input field now when this text changes we get an event and that event has a value for the current target the target of that event being that input and within that Target we have the current value that would be the last thing that the user typed or the last state of the text field so we just set the name to that Target value and again we're using the setter right we don't want to go and say name equals Target value because we know for Strings and for numbers and booleans we get back copies we don't get back the real thing so we can't just set it we got to use that setter set name so now we've got our set let's go take a look and see if that works seems to work pretty well cool so now let's go and add a button so we can add an item to the list now we need to add a click Handler that is going to respond to clicking on ADD name to add that name to that list okay so here we have ADD name so how are we going to implement on this well what we could do is we could just say push the name onto list all right let's go check this out I'm gonna go and add some just random text in there I'll hit add name and nothing happens but here's an interesting deal if I change the state of the component we'll get a re-render so if I hit backspace that's going to change the state of the name field which calls set name set name then does two things it says the name and it also enqueues a re-render request for this particular component when the re-render happens we get that same list and then we print it out now that's the big difference here between scalars and references so strings numbers and booleans are scalars you get back the value a copy of the value and then that's it you've got the local copy but when it comes to objects and arrays JavaScript manages those by reference and when you give react a reference to this particular array it then holds not the array data itself but it holds a reference to that array and then it gives us back that same array reference we then use an In-Place command push to mutate that data of that array in place and that's why as we add more items when we do a refresh we actually get that updated data the problem is that react has no idea that we've done that so the second part of what a Setter does which is to enqueue a request for a re-render of the component doesn't happen so what if we did this what if we said setlist and we'll just give the same list again I mean hey you know we've made a change let's just go and re-render okay let's try that so hit fresh add the name again and nothing happens so here's the deal when I call any Setter when it comes to you state it looks at the old value and it looks at the new value and if the old value and new value are the same it just says I don't I don't care thanks but you know I didn't you know you're not really doing anything so what we're doing in this case is we are giving it back exactly the same reference as we had before so it's looking at those two references and saying oh that's the same array and so you're just asking me to do nothing really and so it doesn't enqueue a re-render request so we need to do in order to make this work is instead of in place mutating the array we create a new array that has the contents of the old array plus the new name so the way you do that is we create a new array we give it all of the old array so list in this case and then we give it our new name now we don't have to do that push anymore hit save and away we go even better we can do set name and set that to an empty string then after we add it that's set to an empty string and it's important to know that with react 17 with react 18 . these Setters are batched so you do set list it sets that value it enqueues a request set name runs right after that sets that name again and cues a request to re-render the component react says Hey I've already got one for this component and it just ignores it and then when the re-render comes around both of those values have been set now the last thing I want to cover about you state before we move on to use reducer is that you state also can take a function as a starting point so let's just take our example here of a symbol string and then we'll give it a function and that function will return a string it says Jack and there you go now it's initialized to Jack so the value of doing it this way is that if you've got some sort of complex calculation that you need in the creation of this U State you can do it all within that function and that function will guaranteed only ever get run once when that component is first created let's continue to take a look at Native State Management in react by taking a look at use reducer which is another way to store state in connection with a component just like you state all right let's go and create another example application we'll call this one native use reducer and again this is available to you in the GitHub repository associated with this video and I'll bring it up in vs code let's install it and then run it and bring it up in the browser okay it looks good so let's pair this down again okay we're all cleaned up but before we get into use reducer I do want to talk a little bit about a reducer function in general and a good way to do that would be to open up a typescript workbook and look at the reduce method on an array so let's give ourselves an array of numbers and we want to total of those numbers so let's start with the total and then we'll iterate through all the numbers and then add that to the total and eventually well what do we get we get 60 10 plus 20 plus 30 60. I think that makes sense all right so another way to do that is to use a reducer function so numbers has a function I call reduce and that reduce function takes two parameters it takes a reducer function which returns something and then it takes an initial value so our initial value here would be the same as this total we start off with zero so that's easy enough so this reducer function takes two parameters it takes the current value which would be zero to start and then it takes the number at the given index as it indexes through the entire array so it starts off at 20 10 20 and 30. so we'll call that n and the output of a reducer is the new value for the next iteration so in this case we want to take the existing value so starting at zero and then add on each number as we go through now if we look at this we get 60 as the output how cool is that so this function right here that we pass to reduce is called the reducer and it takes two parameters it takes the current value and then it takes some new value in the case of numbers because we're iterating through an array it takes each one of the numbers as we go through and then the output of a reducer is what the next iterations input will be so this reducer pattern is going to show up in two places in this video it's going to show up in the user reducer example that we're going to build here it's also going to show up in Redux so learning how reducers work is beneficial across state management okay so what do we want to do with use reducer here well we want to rebuild this example of a list of names and then an input name and build it all in one piece of State Management and so we'll bring in user reducer and we'll invoke it and the first thing let's decide on is what's going to be in the state so the state is going to have a list of names start off with an empty array and then it's going to have the current name which will just be an empty string and that is going to be the state so use reducer just like use State returns an array that array has two elements to it the first is the current state so in this case that would be this object here and then it also returns A dispatch and that's a way to invoke the reducer function that we're going to add so let's create our reducer function and the reducer function takes the existing state which I'll just name state and then it'll take some sort of action right and that's what's going to be sent to that dispatch so we'll just call that action so my convention action is usually an object and that object has a type on it and then you use that type and a switch statement to then mutate that state and return a new state based on the data that you get with that action so let's just start with setting that name so create a switch statement and we will switch on a type which comes in from that action so when we dispatch we're going to dispatch an object that has a type on it and then we'll create a case and let's call this one set name because our first thing is we want to be able to set that name for that input field so let's do set name and now we want to return a new version of State so we take all of the existing state and then we have a name that comes in on a key called payload and that's a kind of by another convention you can really rename these Keys all you want but it's very common to see type and payload so the second value that comes out of this array is dispatch and we're going to use that when it comes to our input so let's go create the input here so we're going to have an input where the type is text and the value is the name that comes out of here so that it's right there we get state name and that gives us state.name and then the on change we are going to dispatch and then we're going to give it an object and that object is going to have a type that type is going to be checked here we're going to pass set name and then we're going to give it a payload and that payload is again that Target value so the target of the event is this input and then that value is going to give you your current value so let's take a look see how we go and you know what just to check it let's go and add in a div worry output the current state name all right let's have a look Okay so we've got our input field over here hello oh nice so what's actually happening here so what's actually happening here let's kind of walk through it step by step is we have an input field it has the current name on it and then every time we get a change event which tells us we have some sort of new text we dispatch to this reducer function a type of set name and the payload that then gets given the current state which we know is going to be this names as an empty array and then the current name whatever that is and then an action that action has that type in it set name and then we just create a new object with that state and that payload but let's talk about that whole references and scalars thing and mutating a reference in place so let's just say that we're not going to do that we are going to instead just return state and we'll just set the name to that payload let's see what happens refresh we type and nothing happens and again this is because react is looking at the reference that's coming out of use reducer and saying hey this matches the existing reference so it can't see it's not going to compare by contents it's not going to look at the inside the object and say look the name is different between these two things it's going to look at the reference to the object so that's why we have to create a new object here and then just mutate the fields that we want to mutate so we return all of the existing fields which mean all of names and then we just override the key for name and change it to whatever's coming in off that payload so now we need to allow for the customer to add an item to the array so let's create a new case called add name and we're going to print another new object that new object is going to have all of the existing state again that includes names and names but we're going to override names to be a new array that has all of the existing names in it plus the name that we send with the payload of this action and I think actually also we should just reset the name to there see how easy that is we can actually mutate multiple fields at the same time it's pretty cool all right let's go down here and we'll make a button out of this call this add name and with that on click Handler we will then dispatch add name and you know what actually we don't really even need a payload here because we already have the state so let's go and just do add name so this is going to be state.names we already have just state.name there yeah that makes more sense Okay cool so I think that's really clean right all you're doing is basically say hey just add the name okay let's take a look add name and now we don't really know maybe it added maybe didn't at least it removed the existing name so that's a plus so let's go and see what we have in that list of names to see if we actually added a name pretty cool so as you can see use reducer is a nice way of managing more complex state so in this case we have an object that has two keys in it you can imagine you would have an object would have a lot of data in it a lot of different keys this would be a much nicer way to do that and you could go and take this reducer pull it out of the component code itself and then test it independently and not have to worry about testing it through a react component so I think it's actually a really nice way if you have complex state to model that all right now one more trick I want to show you when it comes to use reducer I really like this one so let's go and call this name list and then we'll make another app component and we'll use name list in there okay so we're gonna go and make ourselves a little user form and in here we're going to have two input fields first and last name so let's make a div and then within that we'll have an input type this text and at this point we'll just say that our value is going to be some State and State that first and then we'll have state.last okay so let's use a reducer for that so we'll say use reducer and we won't specify our reducer function quite yet let's go and set our initial state to have first and last and then we'll get that state as well as a dispatch all right great Okay cool so let's uh invoke user form here and see if it works nice we have two Fields there but they don't do anything so here's the trick and I really love this one so what we're going to do is we're going to combine the state existing state with whatever comes in on the action just like that it's so easy in fact actually we can make it just a little easier how cool is that and now what we can do is over here in our on change we can just dispatch with whatever key we want to change so we send first then first overrides just first but everything else Remains the Same and the same would last so let's give this a try over on last and now you have two fields and let's prove it out let's go and put uh two divs down here first is first step is state that first and we'll make a new div for last perfect that's sweet so you don't have to have a whole raft of seed functions using this little pattern here you can manage very easily large object State and make all the mutations that you want it's a nice pattern when it comes to use reducer all right so next up we're going to take a look at two ways to observe State use callback and use memo so now that we know how to declare State using use State and use reducer let's talk about three hooks that allow you to monitor state that would be use memo use callback and use effect and in this part of the video I'm going to cover just use memo and use callback so we'll talk about use memo because I think it's actually the most simple yet somehow the most misunderstood so I like to think of use memo as use calculated value so let's take a simple example of a list of numbers so here we've defined some State we've got 10 20 and 30 in there in our array and we want to Total it up and in fact we want to use that Nifty reducer pattern that we saw before so how do we do that well we could just do something like this we take numbers we call reduce on it then with that accumulator starting at zero we add each number in succession to that accumulator return the new accumulator and then that gives us our total so we just you know actually just put that down in here but of course I need to ring in use state so let's do that and I'll say like oh there we go total 60. so 10 20 30. together is 60. makes sense now imagine if you will if this array was monstrous huge crazy huge thousands of values well we wouldn't want to recompute that anytime that app re-rendered which is what's going to happen here every time react re-renders our component the entire function gets called so what we want to do is we only really want to recalculate total when numbers changes so let's bring in our friend use memo or use calculated value as I like to call it so how does these memo work well use memo takes a function and that function does the calculation so let's do that first all right so far so good and then it takes a list of dependencies in an array and this is where a lot of folks get into trouble so basically anything that you read from should go into the dependency array so in this case we are reading from numbers and that means we want to put numbers in the dependency rate and what this will do is it will only calculate this total it will only run this function any time numbers changes and in this case numbers won't change because we initialize it but we don't actually add anything to it or change it in any way so let's run it again and there we go so there are two times when you want to use use memo and this is a really good example of one of them the first time you want to use use memo is when you're calculating any value and the process to create that value it might take a while so any kind of complex calculation that you want to do and in this case numbers could be arbitrarily large so that qualifies so no matter what the output is if it's a number a string a Boolean another array or an object that's fine you want to use use memo whenever you've got a complex calculation that you don't want to do on every render you want to just be smart about it you want to make sure that you only run it when you need it the other time you want to use use memo is when you're creating an array or an object and that's because react Compares arrays and objects by reference and so it's important to stabilize references as we've seen before in the start of this video so references are really important you want to keep those stable so let me show you an example of that so we'll start off with a list of names Perfect The Beatles John Paul Jordan Ringo get up go while it's awesome and now let's go and sort those so it creates sorted names and you know what we'll just do an In-Place sort and then let's help with that so now I've got the names but you know what I also want to put the sorted names there all right let's take a look uh okay well let's actually just join that all together using our comma okay all right so we've got a good sorted names on here but we actually have the same sorted list up here so why is that because I mean we start with John Paul George Ringo and then actually names uh-oh okay so what's actually happening here is that sort is doing an In-Place sort it's actually mutating names in place so yeah we're getting a copy of the reference to that array but that array has been sorted so the first thing we want to do is actually copy names before we sort it and then we sort the copy all right so now this looks good we have our original names and we have our assorted names and our original names haven't been touched so let's go back to the code and let's see so this is good but every time this component re-renders it's going to rerun this sort now that's not particularly bad in this case because app is only going to render the once so let's go and put in a use memo around this again we'll make this a function and so what does this depend on well it depends on names so names changes we want to rerun that sort so this use of use memo falls into both categories of one I think it would be important to use use memo first it's an expensive calculation potentially you could have a very long list of names and you don't want to re-run that sort on every single re-render awesome it also falls into my second category which is that it results in an array or an object so this is a really good use of use memo let me tell you about when I don't think you should use memo and that's for very simple calculations for example let's think about adding two numbers together so now we got count one and count two I'm gonna go add buttons for those all right looks good let's give it a try perfect and now we want to get a total of these two so right now that'd be around seven right so let's go and make a total so I'm going to create a count total and I'm going to start off by using a memo and have it add count one to count two and then I'll just put that in the div down here hey nice okay cool I even got back to seven how cool is that all right so this is not a good use of use memo and it's because the calculation is simple and it results in a scalar a number a string or a Boolean so you don't really have to use it at in this case it's really just overhead in this case so all you need to do is just do an in place count one plus count two that's it so now that you know what use memo is let's talk about some of the myths around it the first myth around use memo is it is somehow connected to react memo the two are in no way related so I'm not sure how that happened I guess somebody was like use memo thinking like somehow react memo but it's it's not that it's just use memo is its own thing again think like use calculated value and react memo which memoizes components and is a good performance enhancement in certain circumstances is just completely really unrelated so the other myth that I've heard about use memo is it is a performance killer and I'm not really sure where that comes from I think it might come from the Cs concept of memoization so with classic memoization you memoize a function and then that memoized function remembers every single set of parameters that's sent to it and only if it sees a new set of parameters is a calculator new value otherwise it will send back a value from that cache that it has and that cash could get huge it can get crazy the potential number of parameters you can send to it that come into Torx you just get like a big data in memory hit use memo doesn't do that use memo is a single level memoization all it's doing is basically saying hey let's look at this dependency array is a dependency array the same as the last time that I saw it if it is then I'm just going to give you back the last value that you created otherwise I'm going to allow you to create a new value for the new data and then I'm going to hold on to that but it's only a single level so there really isn't any kind of performance or memory hit when it comes to use memo all right let's talk about use callback so use callback is another kind of misunderstood hook people don't use it when they should should use it when they don't need to let's try and demystify it a little bit okay so we have this list of names right John Paul George and Rango and we have a assorted names use memo so let's go and create a generic component that sorts in a list of incoming strings we'll call it sorted list you give it a list of strings and it sorts them and then displays them so first let's grab this use memo down here we're going to need that and so it's now the sorted list and it will depend on list and then we will return a div that has our sorted list joined cool right so let's go down here and replace the sorted names with a sorted list and we'll give it the list which is our names it looks really good and it's doing its sorting and everything still works so looks good so I want to see how often this sorted list runs so I'm going to make this into a curly brace function and just return that sort and I'll put it in my console log cool and we can see that we are running the sort twice but that's because we're actually mounting the component twice that's our react 18 thing when you're in Dev mode in strict mode in react 18 every component gets run twice so that's not a big deal but let's go and click on all these buttons and we can see that we're not getting run anymore this component is re-rendering I can add that to sorted list render and now we can see that every time I click this count we do get a sorted list render you can see that's 20 right there we're getting 20 times that call by the way this is console ninja that's putting in the console in context like that it's a really excellent extension and it's free you should try it out so okay so now let's go and say that we want to make this sorted list a little bit smarter we want to be able to give this sort function a a sort comparator so let's say that you want to do your string sorting somehow slightly differently so we're going to allow you to have a sort function and we're going to send that sort function on to sort and now I got to Define that sort function so down here we will Define our sort function and we will say that we're going to take two strings and we're just going to compare the two and we'll pass that sort function onto our sorted list nice and so the Sorting still works in fact we can let's see just multiply this by negative one and now we get the inverse we get Ringo Paul John George but we've actually messed up because we don't have our sort function in our list of dependencies because if sort function were to change we were to give it a different algorithm we would want a different result so let's go and add that to our list of dependencies so now let's hit this button a couple of times and now we can see that every single time we render we also run sort so what's happening there well what's happening there is that every time that we re-run app which is every time we click that button because we set the state the state then says you need enqueue a re-render of the app component that then re-runs this whole component all the way down the line and we create a sort function and then we pass it on to our sorted list and now the sort function is the same implementation each time we're not changing the implementation but we are changing the reference every time we're creating a new function every time that we go through this now is it any different if I were to do this is there some magic in react that will make it so that that's not a problem well let's try nope still gets called every single time so there's no difference between doing it in line like this and having it called out like that so how do we stabilize the reference to that sort function so that when we get down here to our dependency array we keep seeing that the sort function is the same every single time well one thing to do would be just to pull this out of the function entirely put up there now I've got this Global sort function give it a try all right so that works we're not getting a complete one-to-one map between rendering and running that sort but I'm not super happy about having this outside of the component like that I don't think that's all that clean I'd rather have it where I had it before like right in the component so how do we do that well we can use use callback for that so we can wrap this function and use callback and then what's the dependency rate well the dependency array in this case is empty because we're not actually using any data that's in this function we're not using total or names or count or any of that this is just a simple stock comparison function we just want to make sure that that reference Remains the Same over time so we're just going to use an empty dependency array there that way we only ever create sort Funk once let's hit save try it again hit a bunch of counts and there we go now we have a stabilized version of our sort function and we will only ever call sort of list appropriately if the list changes or the sort function changes but we're not going to rerun it on every single go so that's why use callback is important so when should you use use callback but you should use use callback if the Callback that you're creating like on click or the unchange or whatever is going on to a nested component as a property so in this case we're passing sort function as a property to the sorted list and you don't know the internals of sorted list maybe it depends on that sort function and if that sort function reference changes it's going to go and update so make sure that you stabilize references that you send to a react component if you're just using a simple HTML element like input you don't need to use use callback for something like unchange it's Overkill the other time that you want to use use call Mac is if you are creating a custom hook which we'll get to in just a bit anytime that you create a callback in a custom hook you want to make sure that you use use callback to do that because you have no idea what the component that's going to use that hook is going to do with that callback and you want to make sure that the reference to that callback is absolutely stable over time all right so the next thing we're going to take a look at is everybody's favorite hook use effect so let's talk about use effect everyone's favorite hook it's not actually that complicated but it does have a lot of foot gun potential in fact it's the hook that is the one that's most often the culprit when it comes to infinite Loops inside of react apps so let's talk about how to do it right and how to avoid those pesky infinite Loops so we have a Veet app here it's called native use effect it's checked into the GitHub repo and the source Linked In the description down below and this is our starting point so it's just a standard Veet app currently it outputs nothing but we do have some extra stuff in here in the public directory we've got a list of names Jack Jill and Jane and then we have corresponding Json files for each one of our people not a particular great API but one of the things that we use use effect for a lot is to make API requests so let's do that let's actually use a combination of u-state and use effect to fetch the names so first we have to Define our data that would be our names we'll start off with an empty array and then let's just print it out let's take a look and now I currently have names with nothing because we have an empty array over here so let's go populate that array well one way we could do that would be to do fetch right here let's go and get our names.json foreign then we get our response back and then we set the names easy peasy lemon squeezy let's take a look and there they are oh wait hold on what's going on here oh oh wow yeah we blew up so here's what's happening so we render app then declares that state names then starts a fetch then that goes off and asynchronously runs we then return our HTML with our names in it eventually this fetch responds we then get this asynchronous then where we get the Json out of it that again asynchronicity responds then we do this then here where we then set the names which starts the whole process over again because what set names does as we know from before it sets the names as state and it enqueues a re-render so it redraws the names which in turn runs app which in turn now goes and gets the new names that we got so yay we're cool good for that but then we start another fetch right away and so we're in an infinite Loop so how do we get around this well we use use effect and use effect would allow us to say hey only go do this thing once so what does use effect do well it takes a function that it is going to call once the Dom is rendered or really whenever react wants to call your use effect but I'm not going to call it right away it's going to hold it and then call it whenever it wants to when the dependency array changes so let's put our fetch inside that and then for a dependency array we'll just use an empty dependency array we're not depending on anything we're not reading anything inside of this use effect so we don't have to put anything in the dependency array so let's save that out and see is this going to work Bingo it works and this Rock Solid stable how cool is that yay now it actually does go and fetch names.json twice so let's talk a little bit about why that's happening and why that's not really a super huge problem so what's happening is with react 18 every time you it renders a component in Dev mode with strict mode enabled it mounts it which renders it it unmounts it which in the case of a use effect should call a cleanup function if we Define one but we haven't defined one here and then it remounts it again and that remounting calls that use effect again so we get called twice and a lot of people freaked out about this and wasn't very weren't very happy about it but that's what it is so if you want to not do that you can actually disable that by removing strict mode from your app over in the main.jsx again this only happens in Dev mode it's not going to happen production but my people got tweaked about it so there we go so let's try it again it refresh and now we only get names.json the ones the ones all right now the use effect we have here is not an infinite Loop this is a solid use effect a good pattern let's go and kind of build on this by taking names and turning into a list of buttons and we click on the button we'll go and load the corresponding data and that will show us how to use dependency array with our use effect and do it safely so we'll start off by mapping our names into buttons we'll turn these into buttons so now when we click on one of these we want to say that that is our new selected name so we need some state to store that so let's call that selected name and we'll start off at null and then if you click on that button we're going to set that selected name to whatever name you just clicked and just to check if this works let's put that in a div down here Jack Joel Jane perfect works great okay so now what we want to do is we want to go and get the data when this selected name changes so let's go and build a use effect where we look at selected name and then we fetch whatever name that is so we'll use a template string here and then we'll give it the selected name.json and let's see so we need some place to store the data so we need a data for that selected person we'll call that selected name details and so down here instead of set names with a response back from the Json we'll do set selected name details and we'll just take that data cool and now we've got our data in there let's take a look so put it in the div down here and we will Json stringify that because it's an object and react doesn't like when we just render objects directly so let's Json stringify that put in our selected name details and see we get all right so we start off with null that's good because we start off with our selected name details as null over here and then as we click on Jill we set the selected name to Jill that then triggers this use effect because this selected name which is now Jill is different from what we had before which is null so we had an array with null in it now we have an array with Jill in it and so that triggers that use effect but here's an interesting little side note we also got a null.json request so what the heck's up with that what happened there is that we started off with the selected name at null and then we came down here and react said hey cool so we're loading we don't know what was in that dependency area before we didn't have a dependency array before so whatever you're going to have in here is going to be different so the dependency rate had an array with null in it and so it ran you that our use effect with a selected name at no which is not what we want so all we need to do to get around that is then to just bracket this in an if and say well hey only go get the data if we actually have a selected name so there we go but now that I've shown you all this this is actually the wrong way to do it because really we are responding to a user event here we are doing this on click we have our data right there what we should do is we should do it right in the Callback so instead of having the selected name and then the use effect what we should do instead is create a callback called like on select name and this is going to be a name and then we'll just go and fetch that name now we can get rid of all this use effect stuff and over here we will just call that on selected name change with the name and let's see how it works perfect and very reliable and no potential problem with use effect and this is something I see a lot where folks use a combination of state and a use effect when in reality they're just responding to some user interaction and they should just go and do the action right at that point it's the simplest thing to do and it's the right thing to do in this case so you really want to as cool as use effect is limit the amount that you use it to just the things where you need it like for example this use effect up here okay so let's talk about when use effect gets a little bit hairy and that's when use effect depends on data that it also writes so to experiment with that let's create a stopwatch component and what this stopwatch is going to do is it's going to have a an incrementing time so it starts off at zero and it just every second goes up by one so we'll return a div it has time with the timer on so far so good so let's bring that down in here and we'll use it there we go time is zero cool so what do we need to do to get this going well we need to use a set interval so now we know that over here to put a set interval right here and just set the time to the time plus one and then do a thousand that just like that fetch that we had before you're going to run into an infinite Loop because every second we're going to set that time that setting of the time is going to force a re-render of the entire stopwatch function which is going to get the new time yay it's going to be one and then it's going to run another set enroll which is going to create lots and lots and lots and lots of intervals so we don't want to do that well we want to go and create one interval so let's go and use use effect for that and we know from before that we want to create an empty dependency right here because we only want this interval to get created once so let's try this out let's see if this works I'm going to hit save and now we go from zero and we go to one let me stick there so what's the deal let's put in a console log and see what's up so we'll do console.log and we'll just put in time what what what's time because that should be going up and up and up right that number so it said save let's go zero to one but if we look back at our code we can see in the console which is out here with cautional Ninja we're just getting a time at zero over and over and over again so what's happening well what's happening is that we first initialized this effect when we got our initial component render and at that time time the value was Zero and what JavaScript did was we created a closure here and we captured time at zero and so now inside of this function time is forever going to be locked at zero so what's one option well we could go and add time in there as a dependency so that when time changes we rerun this and we get a new value for time but that's going to run into the same infinite Loop problem because we're going to go and create interval after interval after interval after interval another option is that there's a secondary way to call a Setter unused it one way is to just give it the new value another way is to give it a function and that function takes the previous value and then you get to return whatever the new value is so in this case that would be time plus one so let's hit save and now we have a working timer if we were to go i

Original Description

React State Management is half of your React app so it is important for React developers to understand. In this full intermediate React tutorial, you will learn how to implement state management using industry best practices. ✏️ Jack Herrington created this course. He is a principal full stack engineer. Check out his channel: https://www.youtube.com/channel/UC6vRUjYqDuoUsYsku86Lrsw 💻 Code!: https://github.com/jherr/fcc-state ❤️ Try interactive React courses we love, right in your browser: https://scrimba.com/freeCodeCamp-React (Made possible by a grant from our friends at Scrimba) ⌨️ (0:00:00) Introduction ⌨️ (0:03:27) useState ⌨️ (0:18:37) useReducer ⌨️ (0:32:29) useMemo & useCallback ⌨️ (0:49:43) useEffect ⌨️ (1:05:59) useRef ⌨️ (1:13:53) Context and Custom Hooks ⌨️ (1:41:48) React Query & React Location ⌨️ (1:57:26) Zustand ⌨️ (2:06:11) Valtio ⌨️ (2:12:44) Jotai ⌨️ (2:20:51) Redux ⌨️ (2:37:56) The new use hook ⌨️ (2:44:26) Recommendations ⌨️ (2:46:07) Outroduction 🎉 Thanks to our Champion and Sponsor supporters: 👾 Nattira Maneerat 👾 Heather Wcislo 👾 Serhiy Kalinets 👾 Erdeniz Unvan 👾 Justin Hual 👾 Agustín Kussrow 👾 Otis Morgan -- Learn to code for free and get a developer job: https://www.freecodecamp.org Read hundreds of articles on programming: https://freecodecamp.org/news
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from freeCodeCamp.org · freeCodeCamp.org · 0 of 60

← Previous Next →
1 React: Production Server Setup Part 2 - Live Coding with Jesse
React: Production Server Setup Part 2 - Live Coding with Jesse
freeCodeCamp.org
2 cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
freeCodeCamp.org
3 Browser history tutorial - Beau teaches JavaScript
Browser history tutorial - Beau teaches JavaScript
freeCodeCamp.org
4 Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
freeCodeCamp.org
5 React: Parameterized Routing with Next.js - Live Coding with Jesse
React: Parameterized Routing with Next.js - Live Coding with Jesse
freeCodeCamp.org
6 React: Dealing with jQuery Issues - Live Coding with Jesse
React: Dealing with jQuery Issues - Live Coding with Jesse
freeCodeCamp.org
7 setInterval and setTimeout: timing events - Beau teaches JavaScript
setInterval and setTimeout: timing events - Beau teaches JavaScript
freeCodeCamp.org
8 Browser and Device Testing - Live Coding with Jesse
Browser and Device Testing - Live Coding with Jesse
freeCodeCamp.org
9 Last Minute Updates - Live Coding with Jesse
Last Minute Updates - Live Coding with Jesse
freeCodeCamp.org
10 Post Launch Updates - Live Coding with Jesse
Post Launch Updates - Live Coding with Jesse
freeCodeCamp.org
11 React: Setting Up Google Analytics - Live Coding with Jesse
React: Setting Up Google Analytics - Live Coding with Jesse
freeCodeCamp.org
12 React: Masonry Layout - Live Coding with Jesse
React: Masonry Layout - Live Coding with Jesse
freeCodeCamp.org
13 Load Balancing Digital Ocean Droplets - Live Coding with Jesse
Load Balancing Digital Ocean Droplets - Live Coding with Jesse
freeCodeCamp.org
14 try, catch, finally, throw - error handling in JavaScript
try, catch, finally, throw - error handling in JavaScript
freeCodeCamp.org
15 Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
freeCodeCamp.org
16 Graphs: breadth-first search - Beau teaches JavaScript
Graphs: breadth-first search - Beau teaches JavaScript
freeCodeCamp.org
17 React: Masonry Layout Part 2 - Live Coding with Jesse
React: Masonry Layout Part 2 - Live Coding with Jesse
freeCodeCamp.org
18 React: WordPress API Live Search - Live Coding with Jesse
React: WordPress API Live Search - Live Coding with Jesse
freeCodeCamp.org
19 Creating WordPress Custom Post Types - Live Coding With Jesse
Creating WordPress Custom Post Types - Live Coding With Jesse
freeCodeCamp.org
20 Dates - Beau teaches JavaScript
Dates - Beau teaches JavaScript
freeCodeCamp.org
21 Miscellaneous Front End Updates - Live Coding with Jesse
Miscellaneous Front End Updates - Live Coding with Jesse
freeCodeCamp.org
22 Merging a Pull Request from GitHub - Live Coding with Jesse
Merging a Pull Request from GitHub - Live Coding with Jesse
freeCodeCamp.org
23 React + Prettier + Standard JS - Live Coding with Jesse
React + Prettier + Standard JS - Live Coding with Jesse
freeCodeCamp.org
24 React: Sortable Responsive Table - Live Coding with Jesse
React: Sortable Responsive Table - Live Coding with Jesse
freeCodeCamp.org
25 Geolocation Sorting by Distance - Live Coding with Jesse
Geolocation Sorting by Distance - Live Coding with Jesse
freeCodeCamp.org
26 Tradeoff Matrix - Agile Software Development
Tradeoff Matrix - Agile Software Development
freeCodeCamp.org
27 The Definition of Ready - Agile Software Development
The Definition of Ready - Agile Software Development
freeCodeCamp.org
28 Getting first React job without experience - Ask Preethi
Getting first React job without experience - Ask Preethi
freeCodeCamp.org
29 React: Google Analytics Click Tracking - Live Coding with Jesse
React: Google Analytics Click Tracking - Live Coding with Jesse
freeCodeCamp.org
30 Submitting a PR to an Open Source Project - Live Coding with Jesse
Submitting a PR to an Open Source Project - Live Coding with Jesse
freeCodeCamp.org
31 Should I go back to school to get CS degree? - Ask Preethi
Should I go back to school to get CS degree? - Ask Preethi
freeCodeCamp.org
32 Hero Section CSS Changes - Live Coding with Jesse
Hero Section CSS Changes - Live Coding with Jesse
freeCodeCamp.org
33 Working Agreement - Agile Software Development
Working Agreement - Agile Software Development
freeCodeCamp.org
34 A day at Pennybox with Co-Founder Reji Eapen
A day at Pennybox with Co-Founder Reji Eapen
freeCodeCamp.org
35 React: Sorting and Filtering Data - Live Coding with Jesse
React: Sorting and Filtering Data - Live Coding with Jesse
freeCodeCamp.org
36 React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
freeCodeCamp.org
37 React: Building a New UI - Live Coding with Jesse
React: Building a New UI - Live Coding with Jesse
freeCodeCamp.org
38 Definition of Done - Agile Software Development
Definition of Done - Agile Software Development
freeCodeCamp.org
39 Getting started with jQuery (tutorial) - Beau teaches JavaScript
Getting started with jQuery (tutorial) - Beau teaches JavaScript
freeCodeCamp.org
40 Making a React Blog with WordPress Content - Live Coding with Jesse
Making a React Blog with WordPress Content - Live Coding with Jesse
freeCodeCamp.org
41 React, NextJS, CSS - Live Coding with Jesse
React, NextJS, CSS - Live Coding with Jesse
freeCodeCamp.org
42 jQuery events - Beau teaches JavaScript
jQuery events - Beau teaches JavaScript
freeCodeCamp.org
43 React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
freeCodeCamp.org
44 React: Working with API Data - Live Coding with Jesse
React: Working with API Data - Live Coding with Jesse
freeCodeCamp.org
45 React: Refactoring Components - Live Streaming with Jesse
React: Refactoring Components - Live Streaming with Jesse
freeCodeCamp.org
46 jQuery effects - Beau teaches JavaScript
jQuery effects - Beau teaches JavaScript
freeCodeCamp.org
47 More React Refactoring - Live Coding with Jesse
More React Refactoring - Live Coding with Jesse
freeCodeCamp.org
48 animate in jQuery - Beau teaches JavaScript
animate in jQuery - Beau teaches JavaScript
freeCodeCamp.org
49 "Finishing" My React Site - Live Coding with Jesse
"Finishing" My React Site - Live Coding with Jesse
freeCodeCamp.org
50 Starting a New React Project (P2D1) - Live Coding with Jesse
Starting a New React Project (P2D1) - Live Coding with Jesse
freeCodeCamp.org
51 React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
freeCodeCamp.org
52 The Agile Manifesto - Agile Software Development
The Agile Manifesto - Agile Software Development
freeCodeCamp.org
53 jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
freeCodeCamp.org
54 React Project 2 Day 3 - Live Coding with Jesse
React Project 2 Day 3 - Live Coding with Jesse
freeCodeCamp.org
55 The INVEST approach to product backlog items
The INVEST approach to product backlog items
freeCodeCamp.org
56 React Project 2 Day 4 - Live Coding with Jesse
React Project 2 Day 4 - Live Coding with Jesse
freeCodeCamp.org
57 Chickens and Pigs - Agile Software Development
Chickens and Pigs - Agile Software Development
freeCodeCamp.org
58 React Project 2 Day 5 - Live Coding with Jesse
React Project 2 Day 5 - Live Coding with Jesse
freeCodeCamp.org
59 jQuery: add and remove DOM elements - Beau teaches JavaScript
jQuery: add and remove DOM elements - Beau teaches JavaScript
freeCodeCamp.org
60 React Project 2 Day 6 - Live Coding with Jesse
React Project 2 Day 6 - Live Coding with Jesse
freeCodeCamp.org

This video tutorial teaches React state management, including native state management, indirect state managers, and direct state managers, using tools like React, React Query, and Redux. It covers topics such as reducer pattern, memoization, and dependency arrays, and provides hands-on experience with building and optimizing React applications.

Key Takeaways
  1. Build a Vite application using yarn create Vite
  2. Install dependencies using yarn
  3. Start the application using yarn Dev
  4. Define state associated with a component
  5. Create a button that displays the current state value
  6. Use an on click event to update the state value
  7. Use the setter function to update state in React
  8. Create a new component to manage an array of names
  9. Add an input field to the component to allow users to add new names
  10. Add a button to the component to add new names to the array
💡 Proper state management is crucial for building robust and scalable React applications, and using tools like React Query and Redux can simplify the process.

Related Reads

📰
Practice Frontend Typeahead Interviews With AbortController and ARIA
Improve your frontend interview skills by practicing typeahead searches with AbortController and ARIA, learning to handle debounce, cancellation, keyboard navigation, and accessibility features.
Dev.to · Karuha
📰
Building Maintainable Frontend Systems
Learn to build maintainable frontend systems for long-term success by following practical guidelines and best practices
Dev.to · Ufomadu Nnaemeka
📰
Using the Publish–Subscribe Pattern in React with Native Browser Events
Learn to simplify component communication in React using the publish-subscribe pattern with native browser events
Medium · JavaScript
📰
I built a small js library to enhance native html attributes instead of using a heavy UI component or writing tons of js
Enhance native HTML attributes with a lightweight JS library, reducing dependency on heavy UI components or extensive JS code
Reddit r/webdev
Up next
Elementor Angie Ai Plugin Tutorial
Quick Tips - Web Desiign & Ai Tools
Watch →