How to Determine When to Use useCallback and useMemo
Both useCallback and useMemo are React hooks for optimizing performance through memoization, but they solve different problems:
Key Differences
| Feature | useMemo | useCallback |
|---|---|---|
| What is memoized | The return value of a function | The function itself |
| Main use case | Skip expensive recalculations | Persist function reference across renders |
| API | useMemo(fn, deps) | useCallback(fn, deps) |
| Typical usage | For computed values | For callbacks passed as props |
When to Use useMemo
Use useMemo when:
-
You have an expensive computation: Examples include filtering, sorting, or any function that slows your component down if recalculated every render.
-
Referential equality matters: When you pass an object or array as a prop to a child component that relies on
React.memoor is a dependency of a hook. -
Dependencies rarely change: The benefit is higher when the memoized value is stable for many renders1234.
Example:
javascriptconst filteredList = useMemo(() => heavyFilter(items), [items]);
When to Use useCallback
Use useCallback when:
-
You need a stable function reference: Essential if you pass a callback to a child component that is optimized with
React.memo, to avoid unnecessary re-renders. -
Function is a dependency elsewhere: For example, if a function is used in
useEffectoruseMemoand should not change unless its dependencies change. -
You want to avoid recreating handlers on every render, especially inside performance-sensitive lists or large component trees12567.
Example:
javascriptconst handleClick = useCallback(() => { doSomethingWith(id); }, [id]);
How to Decide
-
Ask: Am I memoizing a value or a function?
-
Memoize a value →
useMemo -
Memoize a function (usually an event handler or callback) →
useCallback
-
-
Is calculation time or object identity causing re-renders?
-
Expensive calculation? →
useMemo -
Child components re-rendering due to changing function props? →
useCallback
-
-
Does my callback depend on stable dependencies? Only use these hooks if dependencies don’t change often.
Performance Considerations & Caveats
-
Using these hooks unnecessarily can add memory overhead and make code less readable824.
-
Prefer to apply them when profiling reveals re-render or calculation issues rather than using them by default everywhere.
-
If your computations or functions are trivial and don’t cause performance issues, you likely don’t need memoization834.
Summary Table
| Scenario | Recommended Hook |
|---|---|
| Avoiding recalculation of an expensive operation | useMemo |
Passing stable handler/callback to child (React.memo) | useCallback |
| Memoizing array/object for use in dependency arrays | useMemo |
| Stable callback for use in effects/other hooks | useCallback |
In short:
-
Use
useMemofor memoizing expensive values or keeping stable objects/arrays. -
Use
useCallbackfor memoizing functions/callbacks that are passed down or used elsewhere, minimizing unnecessary re-renders or effect runs.
Both hooks are most valuable in complex components or performance-critical paths—don't overuse them without clear benefit1234.