useMemo Performance Optimization Hook in React
The first performance optimization hook we'll look at is useMemo.
This hook helps cache the results of resource-intensive operations between screen redraws and can therefore help avoid unnecessary large calculations. This caching is also called memoization.
Let's see how this works. Let's create a component with a button and a h3 heading:
return (
<div>
<h3>Text</h3>
<button>click</button>
</div>
);
Now let's make it so that when you click on the title, its color changes from orange to green and back. First, let's create a state isGreen:
const [isGreen, setIsGreen] = useState(false);
Let's add a condition for changing the color of the heading to the style header attribute and attach a click handler:
<h3 onClick={() => setIsGreen(!isGreen)}
style={{ color: isGreen ? 'green' : 'orangered' }}
>Text</h3>
Let us also have some value that will increase by one when we click on our button. Let's create a state for it:
const [num, setNum] = useState(0);
Let's add processing for clicking on the button:
<button onClick={() => setNum(num + 1)}>
clicks
</button>
Let us also have some function square, which will return the square of the value num. We will write the result of the function call to the variable result:
const result = square(num);
function square(num) {
return num * num;
}
Let's output result in the button text:
<button onClick={() => setNum(num + 1)}>
clicks: {result}
</button>
As a result, we got the following: when you click on the button, the value of num changes, which is then squared, and when you click on the title, the color of the title changes.
We have a very small component, everything works quickly, despite the fact that when you click on the header to change its color, the entire component is redrawn, and accordingly, the calculations that are tied to the button are also performed again, even though we did not touch it. Now imagine if our calculations were large and everything was recalculated each time.
Let's make our function a little heavier, now it will think a little longer. This way we will simulate long calculations:
function square(num) {
let startTime = performance.now();
while (performance.now() - startTime < 500) {
// Just do nothing ...
}
return num * num;
}
Now click on the title. It turns out that now, due to the long operation of the square function (and we don’t touch the button), we have to wait forever for the title to change color!
Here the useMemo hook will come to our aid. To do this, we need to pass the function that calculates the value that we want to cache as the first parameter; this function must be pure and not accept any parameters. And the second parameter is the dependencies in square brackets, in other words, all the reactive values that participate in the function code. Thus, in result we will now enter the following construction:
const result = useMemo(() => square(num), [num]);
Click on the title again. Now, if we don't touch the calculation button and don't change the value of the num state that way, nothing is recalculated, and React displays the cached value in the button, so our title quickly changes its color.
Create a component App, place a paragraph in it. Create a state text with an initial value 'react', let the state value be displayed as the paragraph text. Let an exclamation mark be added to the end of the text when clicking on the paragraph.
Create another state num, with the initial value 0. Place another paragraph in App. Make it so that when you click on it, num increases by 1.
Now add a function triple to App that takes num as a parameter and returns its tripled value. Put the result of the function call into the variable result. Display result as the text of the second paragraph. Click on the paragraphs one by one, notice how the exclamation marks are slowly added.
Fix this by wrapping the slow triple function in useMemo.