0
0
ReactComparisonBeginner · 4 min read

UseMemo vs useCallback in React: Key Differences and When to Use

useMemo memorizes the result of a function to avoid expensive recalculations, while useCallback memorizes the function itself to avoid recreating it on every render. Both help optimize React components by reducing unnecessary work but serve different purposes.
⚖️

Quick Comparison

Here is a quick side-by-side comparison of useMemo and useCallback to understand their main differences.

FactoruseMemouseCallback
PurposeMemoizes a computed valueMemoizes a function definition
ReturnsMemoized valueMemoized function
Use caseAvoid expensive recalculationsAvoid recreating functions on each render
DependenciesArray of dependencies to recompute valueArray of dependencies to recreate function
Common usageCaching results of calculationsPassing stable callbacks to child components
⚖️

Key Differences

useMemo stores the result of a function call and returns that cached value until its dependencies change. This is useful when you have a costly calculation that you don't want to repeat on every render.

On the other hand, useCallback returns a memoized version of a function itself, so React does not recreate the function on every render. This is helpful when you want to pass a stable function reference to child components to prevent unnecessary re-renders.

In short, useMemo is about caching values, while useCallback is about caching functions. Both accept dependency arrays to control when the memoized value or function updates.

⚖️

Code Comparison

This example shows how useMemo caches a computed value to avoid recalculating it unless the input changes.

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

function ExpensiveCalculation({ number }) {
  const factorial = useMemo(() => {
    console.log('Calculating factorial...');
    const computeFactorial = n => (n <= 1 ? 1 : n * computeFactorial(n - 1));
    return computeFactorial(number);
  }, [number]);

  return <div>Factorial of {number} is {factorial}</div>;
}

export default function App() {
  const [count, setCount] = useState(1);
  const [other, setOther] = useState(false);

  return (
    <>
      <ExpensiveCalculation number={count} />
      <button onClick={() => setCount(c => c + 1)}>Increase Number</button>
      <button onClick={() => setOther(o => !o)}>Toggle Other State</button>
    </>
  );
}
Output
When 'Increase Number' is clicked, 'Calculating factorial...' logs and factorial updates; clicking 'Toggle Other State' does not recalculate factorial.
↔️

useCallback Equivalent

This example shows how useCallback memoizes a function so it keeps the same reference unless dependencies change, preventing unnecessary re-renders in child components.

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

const Button = React.memo(({ onClick, children }) => {
  console.log('Button rendered');
  return <button onClick={onClick}>{children}</button>;
});

export default function App() {
  const [count, setCount] = useState(0);
  const [other, setOther] = useState(false);

  const increment = useCallback(() => {
    setCount(c => c + 1);
  }, []);

  return (
    <>
      <div>Count: {count}</div>
      <Button onClick={increment}>Increment</Button>
      <button onClick={() => setOther(o => !o)}>Toggle Other State</button>
    </>
  );
}
Output
Clicking 'Increment' increases count; 'Button rendered' logs only once unless dependencies change; toggling other state does not re-render Button.
🎯

When to Use Which

Choose useMemo when you want to cache the result of an expensive calculation or derived data to avoid recalculating it on every render.

Choose useCallback when you want to memoize a function so that it keeps the same reference between renders, especially when passing callbacks to optimized child components to prevent unnecessary re-renders.

In summary, use useMemo for values, and useCallback for functions.

Key Takeaways

useMemo caches computed values to avoid expensive recalculations.
useCallback caches functions to keep stable references across renders.
Use useMemo for derived data and useCallback for event handlers or callbacks.
Both hooks depend on dependency arrays to update their memoized results.
Proper use of these hooks can improve React app performance by reducing unnecessary work.