almessadi.
Back to Index

useMemo Only Helps When the Dependencies Stay Stable_

React memoization depends on identity, not visual similarity. If upstream references keep changing, `useMemo` often adds complexity without delivering the expected win.

PublishedNovember 25, 2024
Reading Time7 min read

useMemo feels like it should cache "the same value," but React does not compare business meaning. It compares dependency identity. If an array or object is recreated on every render, useMemo sees a new dependency and recomputes anyway.

That is why so many memoization attempts do nothing measurable.

The Common Mistake

This looks correct:

const sorted = useMemo(() => expensiveSort(items), [items]);

But if the parent rebuilds items each time:

<Dashboard items={[...rawItems]} />

the memo never really sticks. The child is correct. The input is unstable.

Where useMemo Actually Pays Off

Memoization tends to be worth it when one of these is true:

  • the derived computation is expensive
  • the value is passed into a memoized subtree
  • referential stability affects downstream rendering behavior

It is usually not worth it for tiny computations that exist only to make the code feel optimized.

The Better Mental Model

Good memoization starts upstream. First stabilize the inputs or stop recreating data structures unnecessarily. Then profile. Then add useMemo only where it reduces real work.

That matters even more as React tooling changes. The React Compiler can automate some optimization paths, but it does not remove the need to understand identity and data flow.

Practical Rule

Do not add useMemo because a value is "derived." Add it because profiling shows the recomputation or downstream re-render cost is worth trading for the extra complexity.

Further Reading