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.
| Factor | useMemo | useCallback |
|---|---|---|
| Purpose | Memoizes a computed value | Memoizes a function definition |
| Returns | Memoized value | Memoized function |
| Use case | Avoid expensive recalculations | Avoid recreating functions on each render |
| Dependencies | Array of dependencies to recompute value | Array of dependencies to recreate function |
| Common usage | Caching results of calculations | Passing 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.
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> </> ); }
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.
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> </> ); }
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.useMemo for derived data and useCallback for event handlers or callbacks.