# React.memo vs useMemo vs useCallback: When to Use Each

> A clear comparison of React.memo, useMemo, and useCallback — what each one does, how they differ, and the conditions that justify reaching for each one.

- **Published:** 2026-01-12
- **Author:** Clixo
- **Reading time:** 5 min read
- **Tags:** react, react-memo, usememo, usecallback, memoization, comparison
- **Canonical URL:** https://clixo.sh/blog/react-memo-vs-usememo-vs-usecallback

The three memoization tools in React — `React.memo`, `useMemo`, and `useCallback` — are often conflated. Developers use one when they need another, or use all three together hoping something sticks. The confusion is understandable: all three are about avoiding work, but they operate at different layers and solve different problems.

This comparison clarifies what each one does, when the conditions for using it are actually met, and what to check before reaching for any of them.

## What Each One Does

**`React.memo`** is a higher-order component that wraps a component definition. It prevents the component from re-rendering when its parent re-renders, as long as the component's props have not changed by reference. It compares the previous props to the new props using shallow equality after every parent render.

**`useMemo`** is a hook that memoizes the return value of a function. It runs the function on the first render, caches the result, and only re-runs the function when a value in the dependency array changes. It lives inside a component.

**`useCallback`** is a hook that memoizes a function definition itself. It returns the same function reference across renders as long as the dependency array has not changed. It is equivalent to `useMemo(() => fn, deps)`.

## React.memo vs useMemo vs useCallback: The Core Difference

The distinction that matters most:

- `React.memo` controls **whether a component renders at all**.
- `useMemo` controls **whether a value is recomputed**.
- `useCallback` controls **whether a function reference is recreated**.

They are not interchangeable, and using one without the other is often pointless.

### The dependency between React.memo and useCallback

`React.memo` only works if all props are stable. If a parent passes a callback to a `React.memo`-wrapped child, and that callback is recreated on every parent render, `React.memo` does nothing — the child re-renders anyway because the prop reference changed.

`useCallback` makes the callback reference stable. But `useCallback` alone — without `React.memo` on the child — also does nothing for re-render prevention. Both need to be present together for the combination to work.

This is the most common pairing mistake: a developer adds `useCallback` to a handler but does not add `React.memo` to the child, or adds `React.memo` to the child but passes an unstabilized callback.

## When React.memo Is Justified

`React.memo` is useful when:

1. A component re-renders frequently because its parent re-renders frequently.
2. The component is measurably expensive to render (confirmed with the Profiler).
3. The component's props are stable in practice — primitives, or references that are already memoized.

If any of those three conditions is not met, `React.memo` adds comparison overhead for no benefit.

> A component that renders in 1ms does not need `React.memo`. The shallow prop comparison may cost nearly as much as the render itself.

## When useMemo Is Justified

`useMemo` is useful when:

1. A computation inside a component is genuinely expensive — sorting or filtering a large dataset, running a reduction over many values.
2. The result of that computation is used in another hook's dependency array, and you need to avoid re-running that hook unnecessarily.
3. The computed value is passed as a prop to a `React.memo`-wrapped child, and the value must not change reference unless the inputs change.

`useMemo` is not useful for trivial computations. Calculating a formatted string, adding two numbers, or accessing a property does not benefit from memoization — the dependency comparison costs as much as the computation.

## When useCallback Is Justified

`useCallback` is useful when:

1. A function is passed as a prop to a `React.memo`-wrapped child component.
2. A function is listed as a dependency in a `useEffect` or another hook, and you need it to remain stable to avoid unintended re-runs.

Outside of those two cases, `useCallback` adds complexity without benefit. Functions that are only called inside the component that defines them — and never passed down or used as dependencies — do not need to be wrapped.

## A Decision Table

| Goal | Tool |
|---|---|
| Prevent a component from re-rendering when props are unchanged | `React.memo` |
| Cache an expensive computed value | `useMemo` |
| Stabilize a function reference for a child or hook dependency | `useCallback` |
| Both prevent child re-renders AND stabilize its callback | `React.memo` + `useCallback` |

```mermaid
flowchart TD
  A["What is your goal?"] --> B{"Prevent child from re-rendering?"}
  B -->|Yes| C["Add React.memo to child"]
  C --> D{"Child receives callback props?"}
  D -->|Yes| E["Wrap callbacks in useCallback"]
  D -->|No| F["React.memo is sufficient"]
  B -->|No| G{"Cache an expensive computed value?"}
  G -->|Yes| H["Use useMemo"]
  G -->|No| I{"Stabilize function for hook dependency?"}
  I -->|Yes| J["Use useCallback"]
  I -->|No| K["No memoization needed"]
```

## What to Do Before Reaching for Any of Them

Profile first. Open React DevTools Profiler, record the interaction that feels slow, and confirm which components are rendering and why. Nine times out of ten, the fix is structural — state colocation, context splitting, moving components — rather than memoization.

Memoization is a tool for performance tuning after the architecture is already correct. Using it to paper over structural issues adds complexity without addressing the root cause.

When the Profiler confirms a component is both slow and re-rendering unnecessarily, apply the tools in this order: `React.memo` on the child, `useCallback` on any unstable callbacks passed to it, `useMemo` on any unstable non-primitive props. Then profile again to confirm the improvement.

If your team is working through React performance issues on a live product, [Clixo does targeted engineering work](https://clixo.sh/#contact) — not consulting decks, not generic recommendations.

---

Clixo · 1141 W Bryn Mawr Ave, Itasca, IL 60143, US · [hello@clixo.sh](mailto:hello@clixo.sh)
[Start a build](https://clixo.sh/#contact) · [All services](https://clixo.sh/services) · [Agent guide (llms.txt)](https://clixo.sh/llms.txt)
