useMemo
Last updated
Last updated
As apps become larger and more complex, writing efficient React code is becoming more and more important than ever. Re-rendering large components is expensive, and giving the browser a significant amount of work through a single-page application (SPA) increases processing time and may drive away users.
A common concern among those who work with React js stands for performance. React is fantastic, and if used correctly, there should be no re-rendering issues when states change.
First, let's understand the concept of memoization and why we need it.
In computing, memorization or memorization is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.
Memoization: a performance optimization technique which eliminates the need to recompute a value for a given input by storing the original computation and returning that stored value when the same input is provided. Caching is a form of memoization. Here's a simple implementation of memoization:
Functions in JavaScript are first-class citizens, meaning that a function is a regular object. The function object can be returned by other functions, be compared, etc exactly like an object.
But if we have one function and run it twice setting it to two different variables and compare it (like below), this will return false
and we have the same logic applied to objects
The hook useMemo
receives two parameters: a function that will compute and return a value and an array of dependencies (like useEffect
).
During initial rendering, useMemo(compute, dependencies)
invokes the compute
function memorizes the calculation result, and returns it to the component.
If during next renderings the dependencies don't change, then useMemo()
doesn't invoke compute
but returns the memorized value.
But if dependencies change during re-rendering, then useMemo()
invokes compute
function memorizes the new value, and returns it.
If your computation callback uses props or state values, then be sure to indicate these values as dependencies:
This hook is normally used when we have some calculation based on a prop (like the example below) or when we want to memorize a component with the props sent.
Every time you change the input value, the factorial is calculated factorialOf(n)
and 'factorialOf function has been called'
is logged to console.
On the other side, each time you click Re-render button, inc
state value is updated. Updating inc
state value triggers <Factorial />
re-rendering. But, as a secondary effect, during re-rendering the factorial is recalculated again — 'factorialOf function has been called'
is logged to console.
How can you memorize the factorial calculation when the component re-renders? Welcome useMemo()
hook!
By using useMemo(() => factorialOf(number), [number])
instead of simple factorialOf(number)
, React memorizes the factorial calculation.
You can play with the example below and try the two scenarios with useMemo and without
Nothing is bulletproof in real life, so even those hooks that were made to improve performance in some cases will slow down your app.
Performance optimizations are not free. They ALWAYS come with a cost but do NOT always come with a benefit to offset that cost.
To have the memorization working React needs to deal with this data, calculate it and save it (deals with a garbage collector, etc). My opinion is that those hooks should only be used if:
You have some calculations that will be computationally expensive
When you need to compare it (like the case of passing a function down to a Child Component)
While useMemo()
can improve the performance of the component, you have to make sure to profile the component with and without the hook. Only after that make the conclusion whether memoization worth it.
When memoization is used inappropriately, it could harm the performance.