Mastering React Memo

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
react memo use memo use callback should you use them when should you use them interesting questions let's find out on this video hi i'm jack harrington a principal full stack software engineer and i love doing viewer request videos and this one comes in from alter demon he asks just to request can you please make a video on memoization in react like when to use react memo use memo and use callback i gotta tell you i had some preconceived notions going into this as well and through my research i found out that they were wrong so there's lots of interesting stuff around this let's figure out when you should use react memo and if you should use it and also when you should use use callback and use memo let's jump right into it all right so we have my terminal here and i'm in my 2022 directory and i'm going to do yarn create and then react app and create a new app called react memoization where we will play around with react memo all right now that that's done let's bring it up in vs code all right open the console and from there i'll do yarn start just to bring it up and we're looking good okay so i'm gonna go and clean this up because we really don't need most of this so let's get rid of the logo and also all the contents and i'm just gonna change the css so that it's basically just a margined area and i'm going to zoom in a little bit so we can all see it get rid of the rest okay cool and we have a nice blank white sheet of paper to start our exploration of react memo so the first thing we're going to want to do is understand when this app renders and control in this app render so we can control the rendering of some memoized components that we put inside of the app so let's put a console login here it says app rendered and we'll hit refresh now in our console we can see that we get that app rendered but there's no way to force a re-render so i'm going to add a button and some state and that's just going to allow us to force a re-render all right so now to force a re-render i just need to create some state and then change that state so that it gets automatically updated so i'm going to call that app render index and i'll have a set app render index and so for that i need some use date and then in here i'm gonna go create a new div and then within that a button which is going to on its own click set that app rendered index to app rendered index plus one we'll call that re-render app and then to finish this off i'm just going to put this into here so we can know which render we are on doesn't really matter but we just want to be able to see the different lines in the console okay let's give it a go so now i can click this and every time i click it it's going to re-render the app because the state changes and that's going to force react to do a re-render so to test out memorization i'm going to create a swatch component and it's going to take a color and it's going to put a swatch of color out there so it's going to return a div and in that div we'll just have a style where we'll have it be a square so we'll have the width at 75 say and the height also at 75. let that background color be that color and i'll just put a little bit of margin around it and there we go okay so now let's say that we want to swatch and put another div down here and put in a swatch of color is sure red that looks good okay and yeah nice we got a nice red cube and let's see when that's getting rendered so i'm going to add a rendered on that as well so i'll go back up to here and i'll say console.log and then we'll say swatch rendered and we'll give it the color okay let's take a look i'm going to re-render app a couple of times here and we can see that every time we render the app we also render that swatch which is as we would expect because swatch is not memoed so let's go take a look at how to go and memo swatch i'm going to bring in memo here and then i'm going to create a new component called memo'd swatch by passing swatch to memo now memo is a high order function it creates components so you give it a component and it wraps it and creates another component in this case it's called memo swatch so let's replace this and now every time we do app rerender we don't actually render swatch more than once we maintain its contents and we don't re-render it okay so now let's go and flip this color so we can see when that memo actually runs when how often do we then run swatch so i'm going to go and create a new piece of state here we'll call it color and again we'll start a red sure why not and we'll just pass that in as the prop and then i got to make another button and we'll call this change color and then here we'll do set color and we'll say if the color equals red then make it blue otherwise make it red all right so here we go i'm going to change color and yeah we re-render swatch as blue and if i do re-render app we have kind of locked in that swatch on blue and we're not going to re-render it cool but what do you think's going to happen if i hit change color over here all right to investigate this let's start off with the wikipedia definition of memoization so wikipedia says memoization is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again okay interesting so to experiment with this a little bit more before we find out exactly what happens i'm going to go back into our vs code and i'm going to bring up a quakka sheet and into this sheet i'm going to create a swatch function that takes a color and it's going to console log out that i got called and then it's going to return something like swatch with a color and now we can call it and let's start with red and the output of that is swatch red and then we can see up here that we rendered red let's just make this a little bit shorter so we can see this a bunch of times and then i'll do say red again and now i get red twice and then i'll do blue [Music] and i can kind of flip them like this so i did swatch res watch blue and now we can see that every time this one can use it because it's called we get this output over here so every time we call a swatch we are essentially recalling it so how do we memoize swatch well there's a really good function in low dash called memoize so bring that in and what you do with that is you'd say memoed swatch equals and then memoize and you just give it that function and now let's call memo swatch instead and so now we can see that swatch only gets run twice we get run once for the red and then once for the blue and it stores all of those results in an array or an object referenced by the input value and then when you ask for the same value again you get the same value back so you could ask for red as many times as you want it's just going to give you back that cached result okay so now that we see what memoization is in low dash and i think the traditional definition of memoization let's go see how that works over in the browser all right now we are back where we started i'm hit change color and now we re-render red again interesting so if i do render app yep exactly so now it's locked on red but it did re-render the red so why is that well the definition of memoization in react is different from the kind of classical definition of memoization it doesn't keep a log of all of the components based on the props that you sent in what it does is it only compares the previous props to the new props and when those props have changed it re-renders that's all memoization is compare the old prompts to the new prompts and when the props have changed re-render so let's go back into quakka and see how we would implement that as a react version of the memoization function so the first thing i need to do is have a concept of the previous state so i'm going to call that previous and within there i'm going to have the color which i'll start off at null and then the result which we'll just start off at null and then we'll create a function called react memo for swatch and we'll give it a color and then it's just going to look to see is the color coming in equal to that previous color and if it is then return the previous result otherwise otherwise we want to set that previous color to the color and then we want to set the result to the output of swatch so we're going to call swatch on that color and then return that previous result so we cache it now all these little white boxes mean we haven't actually run it yet so let's run it and we'll do red there all right so the output of that is swatch red as we'd expect cool and now over here we can see swatch red swatch blue swatch red again and that's because we have essentially a new memorization function in here so let's get rid of these calls so we can be a bit more clear about what we got so we got swatch red cool and now if we get swatch blue then we get blue as the output and we get swatch white swatch blue and let's do the same thing again let's flip that again so we go red blue red blue and now we can see we're just getting called over and over and over again red blue red blue and we never actually hit this cache and that's because we're not asking for the same value again so this is the reason why we've gone through this exercise of creating this quacker sheet so you can understand when memoization works in your favor and when it doesn't because it's not the standard version of memoization so in here we have essentially the worst case scenario we're going back and forth between two values or we have a monotonically increasing value if you never have the same props going into the component you're actually going to pay an overhead here to go and check those results so you don't want to memoize functions like that you what you want to do is memoize functions where you're using the same prompts over and over and over again for example if i do red red blue blue then i'm only going to call that function twice because i'm going from one state to another only once so i go from red to blue and there you go so this is actually the best case scenario and then this is your worst case scenario so you really just have to understand the call patterns that you're going to use to your components are you going to change those props a lot are they going to be locked in when the app first starts and that's it it's that second case when the when you have those values locked in that's when you want to use memos okay but now let me go back to app.js and further refine this a little bit more so i'm going to go and create another memo swatch but in this case it's going to be the opposite color so if the color is red then this one is going to be blue and otherwise it's going to be red it's basically going to alternate so we've got a red one and a blue one let's refresh and then when i change color we can see that they both update and that's the really important part to learn here is that that cache that memoization cache is really just for that instance of the swatch it's not for swatch as a function it is for the instance of that swatch on that page if you want to do this in our quanka sheet what we'd have to do is do essentially create swatch and then in here we create what's called a closure where we stored previous and now i'm going to return this function and now i can do say swatch one create that swatch and we'll have swatch one just go from red to blue and now i'll have swatch two now let's see what's going on here so i've got red and blue on one swatch i get red and blue now if i do the same thing for swatch two what do we think is going to happen well we another set of red and blue and the reason being that this previous state is only specific to this particular swatch just the same way that in react the previous state is only specific to the given component and they give an instance of that component so really the important thing to do is just remember that memo is not really memoization react.memo is really react.render if the props have changed so now that you know what react memo is and does question is should you use it so let's go take a look at our react docs and we'll go into react memo as we can see down here there is a caveat this method only exists as a performance optimization do not rely on it to prevent a render as this can lead to bugs and i got to tell you that's really good advice of course don't prematurely optimize but also don't worry too much about react rerenders now let me give you my perspective and it's based on a little bit history so back before react back in like the old jquery days we were driving our ui off of data like we do nowadays we go get some fetch calls and we get some data back and now we've got some data we got to put it on the screen right and so now in our jquery world we go and take that data and then we would use some javascript look at the data and make some element changes on the dom using jquery and so we would alter the dom directly and the problem was that oftentimes bugs would lead to the data and the dom being out of sync and so as a result what we ended up doing was really just replacing most of the dom with essentially a re-rendered piece of data which is the worst thing you can do when you replace a large chunk of the dom you get reflows you get repaints and you get a bad experience but it was the only way to really ensure that the connection between the data and the dom was such that there wouldn't be any synchronization issues which were really bad right so react came along with a different concept the concept was okay we'll start with that data again but now that you're going to use a set of components and you're going to turn that data into a virtual dom not the real dom an in-memory dom and then react is going to do the work of reconciling the dom versus that vdom and so the optimization was you can go and do this render re-render of react as many times as you want this is really actually very efficient react is going to do this vdom to dom reconcile and then change the dom only when it's necessary which is the really important part here it only actually changes the dom when there is a delta between the v dom and the dom so if you're just re-rendering the same component to the same thing over and over and over again that's really not all that bad of a deal yeah sure react create element is a little bit of time but it's certainly nothing in comparison to changing the dom and getting repaints and reflows so react is already hyper efficient when it comes to re-renders and you don't really have to worry about it all that much if you're trying to prematurely optimize and you're basically saying i don't trust that this part of it is fast and it actually is fast i mean there are faster things now there's spelt and there's solid which use fine-grained updates and r faster than react but still this is really really fast and it was certainly a lot faster than all of this so i think if you are jumping to memo right away because you put a console log in your components you're like whoa this is getting called all the time don't worry about it because at the end of the day if it doesn't make a dom change then the price isn't all that high of calling that function over and over and over again all right so now that we know a lot more about react memo let's talk about use memo and use callback so memo works really well when you give it primitive values for props it doesn't work so well when you have objects or arrays for props so let's go and experiment with that i'm going to go and change the api service here so we're going to change color to params and then we'll have params.color so we're going to give it an object and then i'll set background color to the params color which means that down here we need to change this to params and then we need to give it an object with a key of color and i'm going to get rid of that second swatch and let's try this out all right so i refreshed the app and when i changed color now i've broken my memo because the problem here is that every time i run through here i'm creating a new object with a new reference it may have exactly the same value but react is doing a shallow comparison of the props and it's doing that for very valid performance reasons you don't want to do a deep comparison of all the props that's going to take forever if you use a shallow comparison which for primitive values is going to look by value that means booleans numbers and strings are all going to compare by value but objects and arrays are going to compare by references so in this case every time we go through here and we create a new object we're creating a new object with the same value but with a different reference there's two ways to get around this one would be to go in here and give memo a second function and that second function tells that memo whether to re-render or not and you get given the previous props and the next props and what you do is you basically say if the previous prompts equal the next props then just return true and let's see here and now we render the app a bunch of times so we can see that our memoization held because now we are looking inside of the object and doing again a primitive comparison of those two strings which is just fine but let's say that we don't want to do that so let's get rid of this and instead we can use use memo and with use memo we can do effectively the same thing so create a new params by using use memo and it's going to return an object with that color and only get rerun if color changes now let's send params onto params and again we render the app and cool our memoization held the reason being is that what use memo does is when this dependency array does not change it returns to you exactly the same result as it had before which in this case is the exact same object reference this is really important when it comes to arrays and objects you want to get back exactly the same reference if you have referential integrity at play so that includes memo functions and that also includes dependency arrays okay so another question i get a lot is should i use a used memo and that's actually a little bit interesting so it really depends on the output and what you're bringing in as input so in this case we are generating a new number so we're taking two numbers we're just generating a new number and we change when that number changes so this is actually a bad case for use memo what you should really do instead is just put this computation straight in there so why is this well this is a primitive value and a primitive value a number a boolean or a string is always going to compare by value so you're not getting any value out of this use memo and you're just paying that performance overhead for looking at this dependency array and running this function and caching that result okay similar sort of thing for a string so we're creating a string here we change that string when first last change and we're creating a primitive value for that and really what you should just be doing instead is just putting this in line again you're avoiding that use memo call you're avoiding this dependency check and you're avoiding this call to this function and of course storing that string result okay but here's a good case so we are creating a primitive value here we are summing up a bunch of numbers using reduce we take the accumulator we add the value here and we start with 0 and that's going to give us a sum of all of the numbers in this array take the numbers as our input and again we create that primitive value it's okay that we're doing a cache here because we don't know how big this numbers might be and so in this case it's really just a potential performance optimization so we're just making sure that we only actually calculate this value when numbers changes and that means that every time we go through the re-render we're not going to go and run this reduce over and over and over again so this is a good use of used memo in this case we're returning an array and i always recommend using use memo when you return an array or an object and we're creating that array by taking the current numbers and just mapping them times 100 just multiplying them and then we have our dependency on numbers so this is a solid used memo we are returning an array that's important and we're doing something that could be potentially complex and we have a performance hit and then finally here's another good use of used memo so you're creating a person object again good to use use memo when you're creating an array or an object and in this case we're just creating a new person by creating a full name and as well copies of the first and last name and then your dependency array is good so again a good use case here because you're creating an object and you want to maintain that referential integrity okay how about use callback so let's go and add an on click handler to our swatch so i'm going to go over here and we're going to say on click and i'm going to set that as the on click prop and now i'm going to go over here and i'm going to set on click to an empty function all right let's take a look now if i hit refresh and i do re-render my app now i've broken memoization again i'm still calling swatch over and over and over again so why is that well if i go back over here and i take out this on click let's see what happens now i haven't broken memoization so the issue is is this on click so what's happening here is the exact same issue that we had with used memo it's a referential integrity issue so where use memo deals with objects and arrays use callback deals with functions and gives you exactly the same function every time when you call it so in this case we're creating a new function every time so let's go bring in use callback and i'll go back down here and i will create on click by calling use callback giving it our callback function and then giving a empty dependency array which means only create it once and then go take that and put that in here and now when i re-render the app that memoization is maintained and the reason is because every time we call use callback we are getting exactly the same function back not the exact same function implementation the exact same function by reference and again that memo is doing a shallow compare and it wants to make sure that those references when it comes to objects arrays or functions are the same so you want to make sure you maintain the same reference not just the same implementation the same reference so let's wrap up with five things to remember when it comes to react memo use memo and use callback the first one is that react memos aren't memoization in the traditional sense remember we did that low dash memoization and it maintains an array for this prop you get this result that's not the way that react works react works at looking at the previous value versus the new values of the prop and then it re-renders if those have changed so the second thing is to just remember that you should rename react memo in your brain to render if the props have changed the third thing to remember is that use callback and use memo are primarily around referential integrity and in particular around the integrity of arrays and objects and functions the fourth thing to remember is round used memo you should use use memo in particular if the calculation that you're doing is computationally expensive and the fifth thing to remember is that re-rendering in react is not a terrible thing react was built to manage that well i hope this helps you understand more about react memo use call mac and use memo if you have any questions be sure to put those in the comment section down below if you like the video hit the like button and if you really like the video of course hit that subscribe button and click on that bell and you'll be notified the next time a new blue color coder comes out
Info
Channel: Jack Herrington
Views: 106,693
Rating: undefined out of 5
Keywords: blue collar coder, jack herrington react memo, React memo, Memo Reactjs, jack herrington, react memo, mastering Memo hoc, mastering react memo, mastering React Memo, react.memo, react.memo HOC, React.memo, React.Memo, mastering memo, useMemo, React useMemo, useMemo react hooks, useCallback react hook, jack herrington useMemo, useMemo Examples, useCallback, React usememo, useMemo reactjs, Mastering React Memo, Mastering React useMemo, mastering useCallback, use memo in react js
Id: DEPwA3mv_R8
Channel Id: undefined
Length: 26min 56sec (1616 seconds)
Published: Mon Feb 07 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.