Understanding useMemo in Reactjs

muthu raja - Oct 16 - - Dev Community

useMemo

In react, when variables are declared inside the component, they get re-created on every render

Normally, this wouldn't be a problem. But,
what if the function is expensive it takes a longer time to execute?
Imagine if there were multiple state variables in the component, each is not dependent on an expensive function. Each state variable update would cause a re-render and execute an expensive function.

This would cause unnecessary delays. This would affect the performance of application and could lead to a terrible user experience.

Take the following example:

function calculate() {
  let result = 0;
  for (let i = 0; i < 1000000000; i++) {
    result += i;
  }
  return result;
}

function App1() {
  const [count, setCount] = useState(0);

  const value = calculate();

  return (
    <div className="App">
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <p>Count: {count}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In this scenario, useMemo entry is needed.

useMemo is a hook used for optimizing expensive calculations by memoizing the result

useMemo memoizes the return value of expensive calculations between renders.

Memoization is a technique that speeds up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again

useMemo can help you tackle this issue.
The useMemo hook should be declared at the top level of your component. It takes the following arguments:

const value = useMemo(expensiveFunction, [...dependencyArray])

Expensive function
If you declare the expensive function outside the component, you should pass the function reference (not invoke it directly) to useMemo. Alternatively, you can define an inline arrow function within useMemo.

Example 1: Function declared outside and passed by reference

// Expensive function declared outside the component
const expensiveFunction = (num) => {
  console.log("Expensive calculation");
  return num * 10;
};

const MyComponent = ({ number }) => {
  // Use useMemo to memoize the result
  const result = useMemo(() => expensiveFunction(number), [number]);

  return <div>Result: {result}</div>;
};
Enter fullscreen mode Exit fullscreen mode

Here, expensiveFunction is declared outside the component, and you pass it by reference to useMemo. The computation only re-runs when number changes.

Example 2: Using an arrow function directly

const MyComponent = ({ number }) => {
  // Use useMemo with an inline arrow function for the expensive calculation
  const result = useMemo(() => {
    console.log("Expensive calculation");
    return number * 10;
  }, [number]);

  return <div>Result: {result}</div>;
};
Enter fullscreen mode Exit fullscreen mode

In this case, the expensive calculation is done within the arrow function passed directly into useMemo. The memoized result is recalculated only when number changes.

Dependency Array
contains list of dependencies for the hook. The expensive function will be called only when one of these dependencies is updated. You can pass state variables or props that are dependent on this calculation. Any other state updates will not trigger the function.

When to use useMemo:
When you have a state dependent on an expensive calculation, but you don't want to run the calculation on every render.

When you declare an array or object inside a component, its reference changes on every render, even though the value remains the same. Wrapping the values inside useMemo maintains referential equality and prevents unnecessary re-renders. This is essential when there's a useEffect dependent on the array or object.

When you are rendering lists using Array.map that do not need to change unless a certain state value changes.

. . . . . . . . . . . . . . .