useMemo Hook
Learn about the useMemo Hook, its use cases and implementation.
Hook: useMemo
#
Now we come to one of the slightly more complex Hooks. The useMemo
Hook accepts a function and a list of dependencies, much like the useEffect
Hook. It returns a memoized value (yes, that is a weird word!)
What’s special about this memoized value is that it is only recomputed when there is a change in one of the values in the dependency array.
The dependency array you pass is important. If you don’t pass in a dependency array to the
useMemo
Hook, its contents will be regenerated on each render, thus undermining its use.
The use of the useMemo
Hook is quite simple. The function expensiveComputedFunction
will only be called when either depOne
or depTwo
changes.
const someMemoizedValue = useMemo(() => {
// ...do your expressions here...
// return a value here
return expensiveComputedFunction(depOne, depTwo);
// passed in dependencies
}, [depOne, depTwo]);
Suitable applications for useMemo#
Much like its sibling (of sorts) the useCallback
Hook (which we’ll learn about in the next lesson), the useMemo
Hook is usually found when it comes time to profile your application for performance optimization.
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 changed or is not expected to have changed. These extra calls can create optimization bottlenecks and are largely unnecessary.
You’ll often find useMemo
dealing with big data items such as graphs, charts, plotting data, and large mathematical equations.
Optimization caveats#
It’s worth a quick mention here that there is a temptation to over-optimize your code, either too liberally or too early. For me, optimization should be kept in mind, but it should be based on as much empirical data as possible.
Try to resist the temptation to pepper your code with
useMemo
anduseCallback
at every opportunity as the complexity you add and the readability you lose are often not worth the trade-off for slight gains in perceived performance.
Building the useMemo example#
Before going on, I’d recommend taking a quick look at the excellent Hooks reference site, useHooks.com by Gabe Ragland. We’ll be using a modified version of Gabe’s useMemo
example in our demo here.
For this demo we don’t have any extra styles to add, so fire up the UseMemoExample.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 upfront.
import React, { useState, useMemo, useEffect } from 'react';
Next, our helper functions:
const getTimeDifference = (startTime, endTime) => {
const res = Math.abs(endTime - startTime) / 1000;
return res % 60;
};
const countLettersInWord = (word) => {
let i = 0;
while (i < 3000000000) i++;
return word.length
};
With getTimeDifference
, we want to be able to work out the time that has elapsed between a passed in start and end time. The passed in times here will be standard JavaScript date time values. We work out the difference, using the modulus operator to divide the result by 60 to arrive at a value in seconds.
For countLettersInWord
we’re employing a bit of a cheat here, or at least, a forced ‘expensive’ computation. In the real world we’d be looking at a big data calculation or math equation processing function, 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 length of the string word
that we pass in as an argument.
We’ll be memoizing the countLettersInWord
function later on as we pretend it is a computationally expensive function.
Defining the default component export#
Now for the main event, defining the default component export. Let’s start by scaffolding out the component before filling it in:
export default () => {
return (
<section>
<h1>Expensive counting functions</h1>
</section>
);
};
Adding the variables#
This page is a preview of Beginner's Guide to Real World React