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:

useMemo

While useCallback is used to memoize functions, useMemo is used to memoize values.

How to useCallback in React

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.