back

Memoization in React: when it helps and when it just adds noise

There's a phase every React developer goes through where useMemo and useCallback end up on basically everything. I went through it too, hard. It feels responsible, like proof you actually cared about performance. Nobody tells you upfront that memoization isn't free, it costs memory, it costs readability, and it leaves you babysitting dependency arrays for the rest of that component's life.

I had a filter panel once. A dozen checkboxes, a search box, wrapped top to bottom in useCallback and useMemo like a security blanket. Looked very responsible on paper. Then I actually opened the React Profiler and watched what was really happening: two re-renders per interaction, under a millisecond each. I was protecting a component from a performance problem it never had in its life. Ripped all of it out, deleted about thirty lines of dependency arrays, and the file was suddenly readable again for the first time in months.

Because that's really the whole point of memoization, and it took me embarrassingly long to say out loud: you're telling React "you already did this work, don't do it again unless something actually changed." That's the entire deal. It's not a performance ritual you perform to look careful, it's a note about work that doesn't need repeating. If the work was never expensive to begin with, that note is pure overhead, you're paying to remember something nobody needed remembered.

So the question I actually ask now is just: is this expensive enough that redoing it matters? Comparing primitives, cheap, do it a thousand times a second and nobody notices. Creating a plain object, cheap. What's expensive is re-rendering a heavy tree, or recalculating something across hundreds of rows on every keystroke. If you can't point at the actual work being repeated, you don't have a case for memoizing it yet, you just have a feeling.

With the React Compiler stable in 19, most of this manual bookkeeping is quietly going away, and honestly, good riddance. The skill that matters going forward isn't reaching for useMemo out of habit, it's still knowing how to open the Profiler, see what's actually re-running, and recognize the handful of spots where the compiler still needs a human to point at the real work.