Skip to main content

Command Palette

Search for a command to run...

The Cost of Thought: Why useMemo Is More Than a Performance Hack

Published
4 min read
N

Writing about my journey to become a React Developer

“The soul never thinks without a mental image.” — Aristotle
“React never renders without recalculating state.” — a modern frontend philosopher

Before useMemo: A History of Forgetting

In the early days of frontend development, we built static sites. You clicked a link, the server sent a new HTML file, and your browser wiped its memory clean.

No state. No reactivity. No memory.
The browser was amnesiac by design.

Then came client-side JavaScript, frameworks like Backbone, Angular, and finally React, and we asked the browser to remember. Remember what a user typed. What they clicked. What part of the UI should rerender. Memory became central to modern web development.

But memory isn’t free. Not for machines. Not for minds.
React had to learn what to remember and when to forget.

The Rise of React and the Cost of Recalculation

React introduced a profound mental shift:

UI is a function of state.

React’s declarative model means the UI is re-rendered based on state, not manual DOM mutations. This simplified development and allowed React to handle performance optimization under the hood via reconciliation, virtual DOM, and batched updates.

So yes, React was efficient, especially compared to vanilla JavaScript or jQuery-style updates.

React was efficient, but it wasn’t selectively forgetful.

React re-renders everything in a component whenever state or props change, even if certain values didn’t actually change.

Let’s say we have this:

const result = computeSomethingExpensive(input);

Every time the component re-renders, even when input is unchanged, the expensive computation still runs.
React doesn’t “remember” that input was the same last time.
It’s not selectively forgetful; it forgets everything on each render by default.

Enter useMemo

React needed a way to selectively remember the result of expensive computations, but only when relevant inputs change. That’s exactly what useMemo does:

const result = useMemo(() => computeSomethingExpensive(input), [input]);

Now, React will only re-run computeSomethingExpensive when input changes; otherwise, it remembers the last result.

I used this in my embed generator GSoC project:

I told React: Only recalculate the embed code if either embedMode or code changes. That’s it. Otherwise. Remember what you knew.

That’s not just optimization, that’s intention.
That’s not just caching, that’s a form of mental modeling.

Deeper Layer:

This is not just a performance feature, it’s a philosophical bridge.

React’s declarative model says:

“I don’t care how things change, I just declare what the UI should look like.”

But in real-world apps, that purity has a cost. Some things, like expensive calculations or large object creations, are too costly to re-run every time, even in a declarative world.

So, useMemo introduces a memory, a form of selective recall, into React’s otherwise stateless rendering cycle.

React says:

“I will re-render everything.”
useMemo says:
“Except this part, only if it’s necessary.

useMemo in the React Ecosystem

But here’s the nuance.

React’s docs warn:

“You may rely on useMemo as a performance optimization, not as a semantic guarantee.”

This means:
Don’t use useMemo to fix logic. Use it to optimize logic.

Memoization is a helpful tool, not something to rely on to fix broken code. It doesn’t stop your logic from running; it just helps skip extra work. If your component works badly without useMemo, the real issue might be with how the code is structured.

When I used useMemo in my generated embed code, I wasn’t trying to fix a bug or change how the app worked. I just wanted to avoid doing the same heavy work over and over again.

The value with useMemo wasn’t something that decided what the app should do; it was just a result I got from other values.

It didn’t change the app’s behavior, but it helped React avoid repeating the same calculation on every render.

I wasn’t fixing a bug….I was being careful with how much thinking the app had to do.

When Not to Use useMemo

You might be wondering, when is it actually not a good idea to use useMemo?

First, avoid it when the calculation is cheap. If the operation you’re memoizing is quick and simple, then adding useMemo can be unnecessary. In fact, it might just make your code more complex without giving you any real performance gain. Premature optimization is a common trap, and useMemo is no exception.

Second, be careful when the dependencies change too frequently. If the values in your dependency array are unstable, useMemo will end up recalculating just as often as if it weren’t there. In that case, it defeats its own purpose.

Third, don’t use useMemo if it makes your code harder to read. Clarity is more important than squeezing out micro-performance improvements. Readable, maintainable code often wins in the long run, especially in teams.

In short, useMemo is a sharp tool. Use it with precision, not paranoia.

Memoization as Mindfulness

To memoize is to remember with care.
To avoid noise.
To rerender only when it matters.

React’s useMemo reminds us: performance is not about being faster. It’s about being more deliberate.

In a world obsessed with doing more, useMemo quietly teaches us to do less, better.