React Hooks - useMemo()

The useMemo() hook is very similar to the useCallback() hook (). It accepts a function as an argument as well as an array of dependencies, and it returns a Memorized Value that only has to be updated when a dependency changes. A fresh value will be computed on each render if no array is provided. See the statement below:

const result = useMemo(() => computeExpensiveValue(counter1), [counter1]);

When should we use it?

The useMemo() hook's main role is to prevent some expensive functions from executing unnecessarily. Simply said, the useMemo() hook only causes a function to execute if one of the dependents (given as the second argument of useMemo) changes.

Think of a straightforward example involving two counters (counter1 and counter2) and a function that requires an expensive (i.e. time-consuming) calculation. The expensive value is produced by our function, computeExpensiveValue(counter1), using the value of counter1. As a result, it is usual for our function to recalculate the expensive value whenever counter1 changes. It also runs again when counter2 changes, which is entirely unnecessary. We refer to it as our application performing poorly. As a result, you have to think about encasing your function with the useMemo() hook anytime your programme runs into problems of this nature.

Let’s understand it using two different examples, without using useMemo and with useMemo.

Case 1: Without useMemo()


import { useState } from "react";

const Example = () => {
  const [counter1, setCounter1] = useState(0); // Counter 1
  const [counter2, setCounter2] = useState(0); // Counter 1
  const expensiveValue = computeExpensiveValue(counter1); 
  // expensiveValue from computeExpensiveValue Function without useMemo()

  return (
    <div>
        <div>
            <h2>Counter 1: {counter1}</h2>
            <button onClick={() => setCounter1(counter1 + 1)}>+</button>
        </div>
        <div>
            <h2>Counter 2: {counter2}</h2>
            <button onClick={() => setCounter2(counter2 + 1)}>+</button>
        </div>
        <div>
            <h2>Expensive Value:</h2>
            {expensiveValue}
        </div>
    </div>
  );
};

// Expensive Function
const computeExpensiveValue = (count) => {
    // Display on console whenever the function gets call
    console.log("This function is running...")
    // Time Consuming Calcuation
    for (let i = 0; i < 1000000000; i++) {
        count += 1;
    }
    return count;
};

export default Example;

Case 2: With useMemo()

import { useMemo, useState } from "react";

const ExampleUseMemo = () => {
  const [counter1, setCounter1] = useState(0); // Counter 1
  const [counter2, setCounter2] = useState(0); // Counter 1
  const expensiveValue = useMemo(() => computeExpensiveValue(counter1), [counter1]); 
  // expensiveValue from computeExpensiveValue Function With useMemo()

  return (
    <div>
        <div>
            <h2>Counter 1: {counter1}</h2>
            <button onClick={() => setCounter1(counter1 + 1)}>+</button>
        </div>
        <div>
            <h2>Counter 2: {counter2}</h2>
            <button onClick={() => setCounter2(counter2 + 1)}>+</button>
        </div>
        <div>
            <h2>Expensive Value:</h2>
            {expensiveValue}
        </div>
    </div>
  );
};

// Expensive Function
const computeExpensiveValue = (count) => {
    // Display on console whenever the function gets call
    console.log("This function is running...")
    // Time Consuming Calcuation
    for (let i = 0; i < 1000000000; i++) {
        count += 1;
    }
    return count;
};

export default ExampleUseMemo;

Conclusion

In the above two examples, we can see that without the use of useMemo hook, even when the value of counter1 is not updates, the expensive function executes causing a delay in the update process. Which is unnecessary as updating the value of counter2 does not have any effect on the expensive function, but the function is still being executed. So after applying useMemo to the expensive function, it does not execute until the value of counter1 is updated as it is dependent on counter1 variable only hence ensuring that the rest of the page does not get affected by the expensive function unless the variables that are used in the expensive function are updated.

I sincerely hope that the majority of you find the approach covered here to be helpful. Thank you for reading, and please feel free to leave any comments or questions in the comments section below.

Post a Comment

0 Comments