React hooks are a relatively recent addition to the React API. In this post, we will tackle a commonly misunderstood hook, useMemo, and see how it compares to usage in class components.
useMemoReact.useMemo allows developers to render function. Here’s an example:
import React from 'react';
require('./style.css');
import ReactDOM from 'react-dom';
import App from './app.js';
ReactDOM.render(
<App />,
document.getElementById('root')
);
The factorial method can potentially be very expensive to execute for large numbers, so, in the code above, I used useMemo to memoize it. It will now only run whenever the counter state changes.
Here’s how it works:
useMemo(expensiveFunction, dependencyArray)
The first argument is the function to be memoized – here it’s called the expensiveFunction. This is typically inlined, but it may be extracted as a function outside of your component if you want. The important thing to note is that executing expensiveFunction should return the desired value. To put that in code:
useMemo(expensiveFunction, dependencyArray) === expensiveFunction()
The next argument to look at is the dependencyArray argument. This is an array that tells React which variable changes to look out for. Whenever any variable in this dependency array changes from the last render, whether it is from props or local state, the expensiveFunction will recompute. In ideal situations, expensiveFunction will only recompute when any variable in this dependency array changes.
You will notice that the function still recomputes values it had previously computed – for example, if you changed counter from 2 to 3, then changed it back to 2, it would still re-calculate for 2. This is important to note because React only memoizes one argument at a time. If you had a very expensive function, you may want to create your own memoization function that caches all computation values instead of the last one.
How does useMemo compare to usage in a class component? Here is how I would implement it:
import React from 'react';
require('./style.css');
import ReactDOM from 'react-dom';
import App from './app.js';
ReactDOM.render(
<App />,
document.getElementById('root')
);
In the code snippet above, you can see that there’s a lot of repetition/boilerplate:
componentDidMountcomponentDidUpdateprevProps/prevState with this.props/this.stateThis can get unwieldy if you have a lot of functions you need to optimize.
Hopefully, this helps you understand how to use React.useMemo and what patterns to look for when shifting your paradigm from class components to hooks.