Beginner's Guide to React useMemo Hook
Learn about the useMemo Hook, its use cases and implementation.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Beginner's Guide to Real World React course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Beginner's Guide to Real World React, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

[00:00 - 00:08] Now we come to the slightly more complex hooks, in this case, use memo. The use memo hook accepts a function and a list of dependencies much like the use effect hook.
[00:09 - 00:21] It returns a memoised, yes it is a weird word, value. What's special about this memoised value is that it only is recomputed when there is a change in one of the values in the dependency array. The dependency array you pass is important.
[00:22 - 00:42] If you don't pass in a dependency array to the use memo hook, its contents will be regenerated on each render, thus undermining its use. The use of the use memo hook is quite simple. To hammer the point home, the function expensive computed function above will only be called when either DEP1 or DEP2 in the dependency array changes.
[00:43 - 01:44] Much like its sibling of sorts, the use callback hook which we'll learn about in the next lesson, the use memo hook is usually found when it comes time to profile your application for performance optimisation. The best employment of this particular hook is to prevent multiple frequent calls to functions that are computationally expensive, especially when their expected value hasn't or isn't expected to have changed. These extra calls can create optimisation bottlenecks and are largely unnecessary. You'll often find use memo used when dealing with big data items such as graphs, charts, plotting data and dealing with large mathematical equations. But we do have some optimisation caveats. It's worth a quick mention here that there is a temptation to over-optimise your code, either too liberally or too early. For me optimisation should be kept in mind but it should be based on much more empirical data as possible. Try to resist the temptation to peppy your code with use memo and use callback at every opportunity as the complexity you add and the readability you lose are often not worth a trade-off for slight gains in perceived performance.
[01:45 - 02:13] Before going on I'd recommend taking a quick look at the excellent hooks reference site usehooks.com by Garebragland. We'll be using a modified version of Gareb's use memo example in our demo here. For this demo we don't have any extra styles to add so fire up the use memo example.jsx file and let's start by defining some imports and helper functions. We'll be using a few hooks here so we're importing them up front. Next our helper functions.
[02:14 - 04:03] With get time difference we want to be able to work out the time that has elapsed between a passing start time and an end time. The passing times here will be standard JavaScript date time values and we work out the difference using the modulus operator and defined the result by 60 to arrive at a value in seconds. For countletters in word we're employing a bit of a cheat here or at least a fast expensive computation. In the real world we'd be looking at big data calculation on maths equations processing functions but here we have a simple while expression that increases a counter i around three billion times. Once that's finished the function just returns the lens of the string word that we pass in as an argument. We'll be memorizing the count letters in word function later on as we pretend it is a computationally expensive function . Now for the main event. Defining the default component export. Let's start by scaffolding out the component before filling it in. First up we need some variables. For starters we'll add some non-hooks variables. WordList is an array of random strings that we're going to use to count later on in the component. Meanwhile time start is set to a brand new date result that will represent the date time stamp of when the component first renders. Next we need some state values using use state. The variable count will be increased each time we click a specific button which will define in the upcoming JSX. With computed time we'll keep track of the time it takes to count the letters in each of our words when the next word count is triggered. And finally current word will hold onto the current word that we're counting the length of. Now to define some functions and most importantly use our new hook. You can ignore the commented outline for now. We'll come back to this when we run the final app. It's going to help us illustrate an important point where we can skip over it for now.
[04:04 - 04:38] The first function handle load next word is going to be called from a button collector we'll add in shortly when we build out the JSX. It looks at the array of words word list and works out the index of the currently selected word. From here it calls set current word to update the current word held instead. It does this by grabbing the next word in the word list array and incrementing the word index by one or setting it back to the start if it's going to overshoot. The next function is where things get spicy. We're finally calling the use memo hook passing an arrow function that returns the value from the count letters in word function we defined earlier.
[04:39 - 05:27] This function is supplied the current word held instead. We're also using current word in the dependency array so that when this changes we'll run the memoized function again to get the new word count. The last bit of logic for us to get down is to use the use effect hook to work out how long it took to render the component. Again we're using the current word as a dependency here so that when it changes we work out the time difference using get time difference we defined at the beginning of the file passing in the start time and the component began rendering and the time now when we call this function. This doesn't have anything to do with the workings of used memo but it will allow us to visually see how long each word's letter count computation took to complete. Our final task is to add in the JSX so we actually see something when we load this puppy up.
[05:28 - 07:19] Underneath the heading level one element we have in our scale in JSX let's add the following. The first paragraph gives us a nice reference to the current word held instead so we can see what's being calculated. Next we get down two buttons. The first will load the next word in the array called a handle load next word function we just defined in the last section. Whilst the second button calls an inline arrow function that updates the count value instead. The final two paragraphs are further visual niceties to highlight what's going on in the app. The first line shows the currently selected word and how many letters it has once it's being calculated. It also outputs the estimated time it took to count the letters in the word. The second paragraph lets us view the count value instead checking to see if it's zero and displaying a slightly different message if the count hasn't been touched yet. Now for the fun part seeing our hard work in action. Just as before make sure you open up the app.js file and comment out all the components in there except for the used memo example. Your app component should look like this. Update and save the file and open the terminal and run the age old yarn start command opening up in your browser to view the result. So sure it's not much to look at but it does a really great job of illustrating the benefit of used memo. You can see that on initial page load and every time we hit the load next word button our marked expensive function is called and the time difference is calculated and then output to the screen. Each word takes about two to three seconds to count because the currently selected word is changed each time we hit that button the memoized function is rerun the component rerenders and the output is updated. If we hit the notch up the count button the component rerenders are the same updating the output noticed how the count is increased but this time the letter count variable is using the memoized function from count letters in word function.
[07:20 - 07:30] That's because although the count variable is changed the current word variable hasn't. Because this dependency hasn't changed we don't need to rerun the expensive function we can just use the memoized value.
[07:31 - 07:54] Just to hammer-home how valuable used memo can be let's hop back to the used memo example component and swap out the letter count variable with the commented out letter count line. Just delete or comment out the first line which uses the used memo hook and uncommon the very next line which is unmemorized. Reload the app and you'll notice that not much has changed when you hit the load next word.
[07:55 - 08:35] However if you hit the notch up the count now you'll see that it takes ages to simply update a single number by one. This happens because the component is re-render ing but instead of being able to use a memoized value for the letter count variable we're having to work it out afresh each and every time. We shouldn't have to because the currently selected word is the same but by not memorizing the return value we perform the calculation on every rerender. You can see how valuable and useful the single line can be when it comes to optimizing our simple app here.
[08:36 - 08:45] In the final lesson in this module we'll be exploring the use callback hook which is often used in partnership with the used memo hook in optimizing application performance.