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.
useMemo
React.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:
componentDidMount
componentDidUpdate
prevProps
/prevState
with this.props
/this.state
This 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.