DEV Community

Cover image for REACT HOOKS - useMemo()
Kirty Meena
Kirty Meena

Posted on

REACT HOOKS - useMemo()

What is useMemo hook

useMemo() hooks is used to prevent expensive calculation on every render by using memoization.

useMemo() returns a memoized value only when its dependencies changes.

What is Memoization

Memoization is an optimization technique. It is used to speed up the computer program/component performance by storing the result of expensive operation and using the stored value if there is no change in the result.

If there is no change in the result of expensive function then it will not be recalculated but the stored value(cached value) will be used.

Optimizing the component using useMemo() hook

let's see an example of how to use useMemo hook and when to use it.

First we need to create a react app. We can do so by using the below command

npx create-react-app myApp

Next I have create a function named ExpensiveCalculation in a js file of same name.

function ExpensiveCalculation(num) {
    console.log("calculating...");
    for (let i = 0; i < 1000000000; i++) {
      num += 1;
    }
    return num;
}

export default ExpensiveCalculation;

Enter fullscreen mode Exit fullscreen mode

the above function is the expensive function which decreases the performance of the component. The above function will add 1 to the num which is passed as a parameter in ExpensiveCalculation.

The for loop checks if the value of i is less than 1000000000, if this is true, 1 will be added to the previous value of num and then function will return the updated num value.

Then I have created a component named AddItems.js in src folder. Let's see how is the performance of the component without useMemo.

import { useState} from "react";

function AddItems() {
    const [items, setItems] = useState([]);
    const [count, setCount] = useState(1);

    // without memoization --> expensive calculation
    const calculation = ExpensiveCalculation(count)

    const addItems = () => {
        setItems((prev) => [...prev, `New item`]);
    };

    const incrementCount = () => {
        setCount((c) => c + 1);
    };

    return (
        <div>
            {items.map((item) => (
                <li>{item}</li>
            ))}
            <button onClick={addItems}>Add items</button>
            <div style={{ display: "flex" }}>
                <h2>Expensive Calculation</h2>
                <button onClick={incrementCount}>calculate</button>
                {calculation}
            </div>
        </div>
    );
}

export default AddItems;
Enter fullscreen mode Exit fullscreen mode

ExpensiveCalculation is assigned to const calculation. No memoization is used here.

There is a button Add Item which add new items and it will be displayed in the browser.

There is another button calculate which will increment the count

Now whenever we click on button calculate the count will increment and count is passed as argument in ExpensiveCalculation.

const calculation = ExpensiveCalculation(count)

In the file ExpensiveCalculation for loop will run and will check if i is less than 1000000000. This will take sometime because 1000000000 is a big value so AddItem will take time to re-render the updated value.

Now when we click on Add Item button, ExpensiveCalcution will run as well and AddItem component will take longer to re-render even though we just wanted to add new item and display it.

Without useMemo hook

Because of ExpensiveCalculation, There is a delay in execution and AddItem component is taking longer to re-render. To fix this performance issue we will use useMemo hook.

To use memoization in react we have to import useMemo hook from react

const calculation = useMemo(()=>ExpensiveCalculation(count),[count])
Enter fullscreen mode Exit fullscreen mode

useMemo hook accepts a second parameter to declare dependencies. in the above code ExpensiveCalculation function will be called only when there is change in count.

with useMemo

We can see that when count value is not changed then function returns the cached value and there is no lag when we click on add item button.

Below is the complete code after using useMemo hook.

import { useState, useMemo } from "react";
import ExpensiveCalculation from "./ExpensiveCalculation";

function AddItems() {
    const [items, setItems] = useState([]);
    const [count, setCount] = useState(1);

    //with useMemo hook
    const calculation = useMemo(() => ExpensiveCalculation(count), [count])

    const addItems = () => {
        setItems((prev) => [...prev, `New item`]);
    };

    const incrementCount = () => {
        setCount((c) => c + 1);
    };

    return (
        <div style={{ display: "flex", displayDirection: "row", gap: "5rem" }}>
            <div>
                {items.map((item, idx) => (
                    <li key={idx}>{item}</li>
                ))}
                <button onClick={addItems}>Add items</button>
            </div>
            <div>
                <h2>Expensive Calculation</h2>
                <button onClick={incrementCount}>calculate</button>
                {calculation}
            </div>
        </div>
    );
}

export default AddItems;
Enter fullscreen mode Exit fullscreen mode

React forget some previously memoized values and recalculate them on next render to free memory. Write your code so that it still works without useMemo — and then add it to optimize performance.

Top comments (0)