DEV Community

Cover image for useMemo vs useCallback in React
Vidya
Vidya

Posted on

useMemo vs useCallback in React

React applications re-render whenever state or props change. In most cases, React handles re-rendering efficiently. However, in large applications with complex calculations or deeply nested components, unnecessary re-renders can impact performance.

To solve this problem, React provides two optimization hooks:

useMemo – Memoizes a value.
useCallback – Memoizes a function.

Although both are used for performance optimization, they serve different purposes.

What is useMemo?

useMemo is a React Hook that stores (memoizes) the result of a calculation and reuses it on future renders until one of its dependencies changes.

Definition

useMemo prevents React from recalculating a value every time the component renders. Instead, it recalculates only when the specified dependencies change.

Syntax

const memoizedValue = useMemo(() => {
  return expensiveCalculation();
}, [dependency]);
Enter fullscreen mode Exit fullscreen mode

How it Works
=> React executes the function during the first render.
=> The returned value is stored in memory.
=> On subsequent renders, React checks the dependency array.
=> If dependencies haven't changed, React returns the stored value.
=> If dependencies change, React recalculates and stores the new value.

Example Without useMemo

function ProductList({ products }) {

  const sortedProducts = products.sort((a, b) =>
    a.price - b.price
  );

  return (
    <div>
      {sortedProducts.map(product => (
        <p key={product.id}>{product.name}</p>
      ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Problem

Every time the component renders:
=> The sorting operation runs again.
=> Even if the products array hasn't changed.
=> This wastes CPU resources.

Example With useMemo

import { useMemo } from "react";

function ProductList({ products }) {

  const sortedProducts = useMemo(() => {
    return [...products].sort((a, b) =>
      a.price - b.price
    );
  }, [products]);

  return (
    <div>
      {sortedProducts.map(product => (
        <p key={product.id}>{product.name}</p>
      ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Benefit

Now sorting happens only when the products array changes.
If another state changes in the component:
=> React re-renders.
=> Sorting is skipped.
=> The stored value is reused.

What is useCallback?

useCallback is a React Hook that stores a function and returns the same function reference across renders until dependencies change.

Definition

useCallback prevents React from creating a new function every time the component renders.

Syntax

const memoizedFunction = useCallback(() => {
  // function logic
}, [dependency]);
Enter fullscreen mode Exit fullscreen mode

Why Do We Need useCallback?

Consider this example:

function Parent() {

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

  const handleClick = () => {
    console.log("Button clicked");
  };

  return (
    <Child onClick={handleClick} />
  );
}

Enter fullscreen mode Exit fullscreen mode

Whenever count changes:
--> Parent re-renders.
--> A new handleClick function is created.
--> Child receives a new function reference.
--> Child re-renders unnecessarily.

Example With useCallback

import { useCallback } from "react";" 

function Parent() {

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

  const handleClick = useCallback(() => {
    console.log("Button clicked");
  }, []);

  return (
    <Child onClick={handleClick} />
  );
}
Enter fullscreen mode Exit fullscreen mode

Benefit
--> The same function reference is reused.
--> Child component doesn't re-render unnecessarily.
--> Performance improves.

Top comments (0)