React ensures your user interface stays in sync with the application state by using a technique called re-rendering. During re-renders, React compares the Virtual DOMs and updates the necessary parts of the UI. This process is known as React Reconciliation.
Although React optimizes re-rendering for speed, some tasks can slow it down, leading to performance issues. To address this, React introduced the useMemo
hook.
What is useMemo?
useMemo
is a React Hook that caches the result of a calculation between re-renders.
Syntax:
const cachedValue = useMemo(calculateValue, dependencies);
useMemo
memorizes values between re-renders, recalculating only when dependencies change. This avoids expensive calculations on every render. To the useMemo
you can pass a function and an array of dependencies and it will only recompute the memoized value when one of the dependencies has changed. This avoids expensive calculations on every render and can improve performances.
Parameters
calculateValue
: A pure function that takes no arguments and returns a value to be cached. React calls this function during the initial render and will return the same result on re-renders unless the dependencies change. If dependencies change, React will callcalculateValue
again and return its result.dependencies
: An array of reactive values referenced incalculateValue
. These include props, state, and variables or functions declared directly in the component body. React recalculates the value if any dependency changes.
Remember, don’t do anything there that you wouldn’t normally do while rendering. For example, side effects belong in useEffect, not useMemo.
Usage
Below are the use cases of useMemo
:
- Skipping expensive calculations.
- Skipping re-rendering of components.
- Memozing a dependency of another Hook and function.
To understand the concept better, let’s dive into the example of skipping the expensive calculation using useMemo
. In the given code, a slow function named slowFunctionNumber is executed every time the component initializes or the input changes. However, it also runs whenever the theme button is clicked, despite the theme button having no dependency on the number function. This unnecessary execution can reduce the application’s performance.
import {useState} from 'react';
// Simulating a slow calculation
const slowFunctionNumber = (num) =>{
for(var i=1; i<10000; i++){
console.log("slowFunctionNumber called.");
}
return num * 2
}
const NonMemoPage = () => {
const [number, setNumber] = useState(0);
const [dark, setDarkTheme] = useState(false);
const onNumberChangeHandler = (e) => {
setNumber(e.target.value);
};
const onThemeChangeHandler = () => {
setDarkTheme(prevDark => !prevDark);
}
// this function will makes the code slower.
const doubleNumber = slowFunctionNumber(number);
const styleClass = {
backgroundColor: dark ? 'white' : 'black',
color: dark ? 'black' : 'white',
minHeight: '100px'
}
return (
<>
<input type="number" onChange={onNumberChangeHandler} value={number}></input>
<br/>
<button onClick={onThemeChangeHandler}>Change theme</button>
<div style={styleClass}>{doubleNumber}</div>
</>
)
}
export default NonMemoPage;
}
In the above example, slowFunctionNumber
artificially slows down the process by running a loop. In real scenarios, complex calculations might be involved, leading to significant performance issues.
To prevent slowFunctionNumber
from running unnecessarily, you can use the useMemo
hook, as demonstrated below. With useMemo
, you can see that slowFunctionNumber
is not executed when the theme change button is clicked. This happens because React memoizes the result and avoids re-rendering when there are no changes in the dependencies.
import {useMemo, useState} from 'react';
// Simulating a slow calculation
const slowFunctionNumber = (num) =>{
for(var i=1; i<1000; i++){
console.log("slowFunctionNumber called.");
}
return num * 2
};
const MemoPage = () => {
const [number, setNumber] = useState(0);
const [dark, setDarkTheme] = useState(false);
const onNumberChangeHandler = (e) => {
setNumber(e.target.value);
};
const onThemeChangeHandler = () => {
setDarkTheme(prevDark => !prevDark);
}
// useMemo will remember the function value if the dependencies is not changed.
const doubleNumber = useMemo( () => {
return slowFunctionNumber(number)
}, [number]);
const styleClass = {
backgroundColor: dark ? 'white' : 'black',
color: dark ? 'black' : 'white',
minHeight: '100px'
}
return (
<>
<input type="number" onChange={onNumberChangeHandler} value={number}></input>
<br/>
<button onClick={onThemeChangeHandler}>Change theme</button>
<div style={styleClass}>{doubleNumber}</div>
</>
)
}
export default MemoPage;
In this above code:
useMemo
is used to memoize the result ofslowFunctionNumber
, ensuring it only re-runs when number changes.- The theme change button now only affects the theme without causing the slow function to re-run, improving overall performance.
Summary
useMemo
is a React hook thats helps optimize performance by memozing the result of functions and ensuring its only re-renders when one of the dependencies are changed.
Use the share button below if you liked it.
It makes me smile, when I see it.