React Hooks review #6: useMemo
This is chapter three, and the shortest of the seven additional React Hooks series, variants of the first three basic hook, but written to handle edge cases. And still, the goal was simple: summarize all the eleven official React hooks:
- The three basic Hooks:
useState
,useEffect
,useContext
. - The seven additional Hooks:
useReducer
,useCallback
,useMemo
,useRef
,useImperativeHandle
,useLayoutEffect
,useDebugValue
. - And understand the endless potential of custom hooks.
useMemo
While
How to useCallback in ReactuseCallback
is used to memoize functions,useMemo
is used to memoize values.
Memorize value to prevent re-evaluating functions if the dependencies list did not change.
Syntax:
const memoizedValue = useMemo(executableFunc, dependencyArr);
- executableFunc: Function that returns some memorizable value.
- dependencyArr: Array of dependencies.
Simple example
Let’s have a simple component with some expensive calculation. And two re-render values, but only one (a) that is related to the calculated value.
const UseMemo = ()=>{
const [a,setA] = React.useState(0);
const [b,setB] = React.useState(0);
const expensiveCalculatedValue = (()=>{
console.log('Starting calculation');
for(let i = 0;i<1000000000;i++){}
console.log('Ending calculation');
return a*10;
})();
return <div>
<p>A: {a}, B: {b}, Calculated Value:{expensiveCalculatedValue}</p>
<button onClick={()=>{setA(a + 1)}}>Change the expensive value</button>
<button onClick={()=>{setB(b + 1)}}>Change some unrelated value</button>
</div>
}
We would expect that changing the related value will recalculate, but we don’t want that the calculation will run if we change unrelated values.
If we wrap the calculation with the useMemo
hook, the calculation will run only if one of its dependencies has changed:
const UseMemo = ()=>{
const [a,setA] = React.useState(0);
const [b,setB] = React.useState(0);
const expensiveCalculatedValue = React.useMemo(()=>{
console.log('Starting calculation');
for(let i = 0;i<1000000000;i++){}
console.log('Ending calculation');
return a*10;
},[a]);
return <div>
<p>A: {a}, B: {b}, Calculated Value:{expensiveCalculatedValue}</p>
<button onClick={()=>{setA(a + 1)}}>Change the expensive value</button>
<button onClick={()=>{setB(b + 1)}}>Change some unrelated value</button>
</div>
}
useMemo keeps in memory the results of the function’s execution. This is why use useMemo only whenever you’re trying to prevent re-running expensive functions, that run a lot of time or using a lot of resources. Else it might potentially grow big and ironically harm the performance of your App.
Can I get the same effect without useMemo
? Yes, with useState
& useEffect
. But this will violate the definition of useEffect
as “an encapsulated area to affect or connect to elements outside the component”.
const UseMemo = ()=>{
const [a,setA] = React.useState(0);
const [b,setB] = React.useState(0);
const [calculatedValue,setCalculatedValue] = React.useState(0);
React.useEffect(()=>{
console.log('Starting calculation');
for(let i = 0;i<1000000000;i++){}
console.log('Ending calculation');
setCalculatedValue(a*10);
},[a]);
return <div>
<p>A: {a}, B: {b}, Calculated Value:{calculatedValue}</p>
<button onClick={()=>{setA(a + 1)}}>Change the expensive value</button>
<button onClick={()=>{setB(b + 1)}}>Change some unrelated value</button>
</div>
}
And since this was a short subject, here is some video that inspired me:
I bought two bags of clay but didn’t have a kiln. I just tried to make pots. I had no reason to keep the pots because I had no way of firing them. So [for about ten years] I just made them and put them back in the bag.
It was a real gift to learn about how clay works and I loved it. I absolutely loved it.