Skip to main content

useCallback vs useMemo

useCallback and useMemo are both hooks in React that are used to optimize performance by memoizing values. However, they serve different purposes and are used in different ways:

  • useCallback is used to memoize functions
  • useMemo is used to memoize the result of a function

useCallback

useCallback is used to memoize functions. It is used to prevent unnecessary re-renders of components. It is used when you have a function that is passed as a prop to a child component and you want to prevent the child component from re-rendering when the function changes.

When to use useCallback:

  • When you pass a function as a prop to a child component that is wrapped in React.memo, you should use useCallback on that function. This prevents the child component from re-rendering unnecessarily because the function prop is a new reference on every parent render.
  • When a function is a dependency in another hook like useEffect, it's crucial to wrap it in useCallback to prevent the effect from running on every render.

Basic Syntax:

const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);

Real World Example:

import React, { useState, useCallback } from 'react';

const ChildComponent = React.memo(({ onClick }) => {
console.log('ChildComponent rendered');
return <button onClick={onClick}>Click me</button>;
});

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

const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []); // Empty dependency array means the function is created only once

return (
<div>
<p>Count: {count}</p>
<ChildComponent onClick={handleClick} />
</div>
);
};

Without useCallback, a new handleClick function would be created on every render of ParentComponent, causing ChildComponent to re-render even though its props haven't conceptually changed.

useMemo

useMemo invokes a function and returns its memoized result. The function is only re-executed if one of its dependencies has changed.

Basic Syntax:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

When to use useMemo:

  • Expensive calculations: When you have a computationally intensive function that runs on every render, you can use useMemo to cache its result and only recompute it when necessary.
  • Memoizing computed values: When you have a complex value that depends on multiple other values, you can use useMemo to memoize that value and only recompute it when necessary.

Real World Example:

import React, { useState, useMemo } from 'react';

const expensiveCalculation = (num) => {
console.log('Performing expensive calculation...');
// Simulate a heavy computation
for (let i = 0; i < 1_000_000_000; i++) {
// Do something
}
return num * 2;
};

const MyComponent = () => {
const [count, setCount] = useState(0);
const [number, setNumber] = useState(10);

const calculatedValue = useMemo(() => expensiveCalculation(number), [number]);

return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment Count</button>
<p>Calculated Value: {calculatedValue}</p>
<button onClick={() => setNumber(number + 1)}>Increment Number</button>
</div>
);
};

In this example, the expensiveCalculation will only run when the number state changes. Clicking the "Increment Count" button will not trigger the recalculation.

Summary

  • Use useCallback for functions you want to pass down without causing re-renders.
  • Use useMemo for values you want to memoize and prevent re-computation.