React useMemo Hook
In Javascript there are some tricky results when we run equality comparisons:'a' === 'a' // true
a === 'a' // false
{} === {} // false
const b= {}
b === b // true
React uses Object.is
to compare components, and it gives a very similar result when using ===
.
() => {} === () => {} // false
[] === [] // false
The above comparison check will cause some unexpected React re-rendering. If the re-rendering includes some expensive operation it will no doubt hinder the performance. Thus, React released the memo idea to fix this.
Memoization
Memoization is basically an optimization technique which passes a complex function to be remembered. useMemo
is a React hook that memorizes the output of a function. In React, memoization optimizes our components, avoiding complex re-rendering when it isn’t intended.
In memoization, the result is remembered, when the same exact parameters are passed-in subsequently.
Memorize hooks need to remember data or functions that:
- Might cause re-render when re-rendering is not needed
- Preserve or cache data or function so new copies are not created.
If we have a function to compute 1 + 1, it will return 2. But if it uses memoization, the next time we run 1’s through the function it won’t add them up, it will just remember the answer is 2 without executing the adding function.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useMemo
accepts two arguments: a function and a list of dependencies. (the array [a, b]
). They act similar to arguments in a function. The dependencies list are the elements useMemo watches. If there are no changes, the function result will stay the same, otherwise it will re-run the function.
useMemo
will call the function and return its return value. Then, every time you call useMemo
again, it will first check if any dependencies have changed. If not, it will return the cached return value, not calling the function. If they have changed, useMemo
will call the provided function again and repeat the process. This can be optimal if the wrapped function is large and expensive. That is the primary use for useMemo.
This should remind you of the useEffect
hook: both useMemo
and useEffect
accept lists of dependencies. The only difference is that useEffect
is intended for side-effects, while functions in useMemo are supposed to be pure and with no side-effects.
If you’re familiar with React’s class-component lifecycle hook, shouldComponentUpdate, useMemo
has a similar usage in preventing unnecessary re-renders.
When to use useMemo
useMemo returns a memoized value
- For computationally expensive calculations
- Referential equality in dependencies list
When to use useCallback
useCallback returns a memoized callback
- Referential equality
When Not to useMemo
The useCallback
hook is similar to useMemo
, but it returns a memoized function, while useMemo
has a function that returns a value.
If you’re performing an operation that’s not expensive, then you don’t need to memorize the return value. The cost of using useMemo
may out weigh the cost of reevaluating the function. If you find yourself in such a situation, I ask that you rethink the use of the useMemo
Hook. You’re memorizing a value that is not an expensive calculation and isn’t recomputed at any point in time.
When looking to implement useMemo
always ask, “is this really an expensive function?” Expensive means it is using up a lot of resources (like memory). If you are defining a ton of variables in a function at render, it might make sense to memoize with useMemo
.
When looking to implement useMemo
, write the code first then revisit it to see if you can optimize it. Don’t start with useMemo
. Too many people implement it quickly and it can make performance worse in a small application.
Hope you got an idea about useMemo :)