Difference between useMemo and useCallback?
In React, `useMemo` and `useCallback` are hooks used for performance optimization through memoization. While both serve to prevent unnecessary computations and re-renders, they target different types of values: `useMemo` memoizes a computed value, and `useCallback` memoizes a function instance.
What is Memoization?
Memoization is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again. In React, this often means preventing re-creation of values or functions on every render.
useMemo
useMemo is a React Hook that memoizes a computed value. It runs a function during the initial render and caches its result. On subsequent renders, if the dependencies provided in the dependency array have not changed, useMemo returns the cached value without re-executing the function. If dependencies change, the function re-runs, and the new result is cached.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
- Purpose: Memoizes a *value*.
- Return Value: The memoized value itself.
- When to use:
- - When you have an expensive calculation that should only re-run if its inputs change.
- - To prevent unnecessary re-renders of child components that are optimized with
React.memoand receive a complex object or array as a prop, where referential equality is important.
useCallback
useCallback is a React Hook that memoizes a function instance. It returns a memoized version of the callback function that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on referential equality to prevent unnecessary re-renders.
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
- Purpose: Memoizes a *function instance*.
- Return Value: The memoized function itself.
- When to use:
- - When passing callback functions as props to child components that are optimized with
React.memo(e.g., to prevent the child from re-rendering just because the parent re-created the function prop). - - To prevent functions from triggering
useEffectoruseLayoutEffecthooks to re-run if they are included in their dependency arrays and their dependencies haven't changed.
Key Differences Summarized
| Feature | useMemo | useCallback |
|---|---|---|
| What it memoizes | A value (the result of a function execution) | A function instance |
| Return Value | The memoized value | The memoized function |
| Syntax | `useMemo(() => computeValue(), [deps])` | `useCallback(() => myFunction(), [deps])` |
| Primary Use Case | Optimizing expensive calculations, ensuring stable values for `React.memo` components | Ensuring stable function references for `React.memo` components, `useEffect` dependencies |
When to Use Which?
- Use
useMemowhen you have a piece of data that is expensive to compute, and you only want to re-compute it when its underlying dependencies change. It helps avoid re-running intensive calculations on every render. - Use
useCallbackwhen you are passing a function down to a child component, especially an optimized child component (wrapped inReact.memo), and you want to prevent that child from re-rendering just because the parent component re-creates a new function instance on every render.
Important Considerations
- Over-optimization: Don't overuse
useMemooruseCallback. There's an overhead associated with these hooks (memory for caching, comparison of dependencies). Use them strategically where performance bottlenecks are identified. - Dependency Array: Always ensure your dependency array is correct. An empty array
[]means the value/function is created once and never changes. Omitting the array means it's re-created on every render (defeating the purpose). Incorrect dependencies can lead to stale closures or unnecessary re-computations. - Referential Equality: Both hooks are critical for scenarios where referential equality (meaning the exact same object/function in memory) matters, such as with
React.memofor props or dependencies in other hooks likeuseEffect.
In essence, useMemo provides a stable *value*, and useCallback provides a stable *function*. Both are powerful tools for optimizing React applications, but should be applied judiciously.