
Stop Using useMemo Everywhere: The Cost of Premature Optimization
Obsessively wrapping everything in `useMemo`? It might be hurting your performance. Learn the hidden costs of memoization and when to actually use it.

Obsessively wrapping everything in `useMemo`? It might be hurting your performance. Learn the hidden costs of memoization and when to actually use it.
Establishing TCP connection is expensive. Reuse it for multiple requests.

Optimizing by gut feeling made my app slower. Learn to use Performance profiler to find real bottlenecks and fix what matters.

Definitely No, Maybe Yes. How to check membership in massive datasets with minimal memory using Bit Arrays and Hash Functions. False Positives explained.

Text to Binary (HTTP/2), TCP to UDP (HTTP/3). From single-file queueing to parallel processing. Google's QUIC protocol story.

I often see code like this during reviews:
// ❌ Obsessive use of useMemo
const TaxCalculator = ({ price, taxRate }) => {
const calculatedTax = useMemo(() => price * taxRate, [price, taxRate]);
const formattedPrice = useMemo(() => `${price}`, [price]);
return <div>{formattedPrice} + {calculatedTax}</div>;
};
Juniors ask me: "Isn't it faster because we skip recalculation?"
But profiling shows this component renders 1.5x slower than the plain version.
To avoid a simple multiplication (*), code performed expensive interactions (Array creation + Dependency Comparison + Memory Allocation).
I naively thought "Skipping calculation is always good."
Coming from Algorithms class, Memoization felt like magic.
So I wrapped every object, function, and variable in useMemo and useCallback.
But React rendering is incredibly fast.
For the V8 engine, price * taxRate takes less than 0.000001ms.
Using useMemo adds overhead:
[price, taxRate].The Overhead was bigger than the Saving.
I understood this with a "Shipping Delivery" analogy.
Only use useMemo when "The cost of calculation" > "The cost of memoization itself."
Delete useMemo in these cases immediately. It hurts performance.
const text = "Hi " + name;const style = { color: 'red' };So when should I use it? React docs verify "Calculations taking 1ms+".
const AnalyticsDashboard = ({ chaosData }) => {
// ✅ 1. Filtering 10,000+ items takes > 50ms
const filteredData = useMemo(() => {
return chaosData.filter(d => heavyComputation(d));
}, [chaosData]);
// ✅ 2. Referential Equality needed
// If this object is used in useEffect dep or passed to React.memo child
const config = useMemo(() => ({ theme: 'dark' }), []);
return <ComplexChart data={filteredData} config={config} />;
};
useMemo and useCallback shine when preventing re-renders of child components.
// Child is wrapped in React.memo (Optimized)
const Child = React.memo(({ onClick }) => {
console.log("Child Rendered");
return <button onClick={onClick}>Click</button>;
});
const Parent = () => {
// ❌ Without useCallback, function reference changes every render.
// -> Child sees "Changed Props" -> React.memo fails -> Re-render occurs!
const handleClick = () => {};
// ✅ useCallback keeps reference stable -> Child re-render prevented
const handleMemoClick = useCallback(() => {}, []);
return <Child onClick={handleMemoClick} />;
};
Basically, if the child component isn't React.memo, useCallback is mostly useless noise.
This debate might end soon with React Compiler (codenamed Forget).
It analyzes code at build time and automatically inserts useMemo and useCallback where appropriate.
Developers won't need to manually manage dependency arrays or worry about memoization. The compiler just optimizes "If value hasn't changed, reuse it."
What we need to learn now is not useMemo syntax, but "Data Flow Design"—distinguishing between mutable and immutable data. Tools get automated, but Design remains human.
"How do I know if it's heavy?" Don't guess. Measure.
console.time('filter');
const result = heavyFilter(data);
console.timeEnd('filter'); // "filter: 0.2ms" -> Don't useMemo!
Or use the Profiler tab in React DevTools. Check "Why did this render?" to see if optimizing props actually helps.
Scary quote from React docs: Current: "React may choose to 'forget' some previously memoized values to free memory."
Means: Don't use useMemo for logic correctness.
"I wrapped this in useMemo, so it won't trigger useEffect!" -> WRONG.
React might discard the cache and re-calculate any time.
If you need a stable reference for functionality, use useRef. useMemo is strictly for Performance.
The most critical place for useMemo is inside a Context Provider.
// ❌ Bad
const UserProvider = ({ children }) => {
const [user, setUser] = useState(null);
// Value object re-created every render!
// -> Triggers re-render in ALL Consumers.
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
};
Here, the value object {...} gets a new memory address on every render.
Consumers think data changed. Result: Full App Re-render.
// ✅ Good
const value = useMemo(() => ({ user, setUser }), [user]);
return (
<UserContext.Provider value={value}>
{children}
</UserContext.Provider>
);
Here, we use useMemo not for math, but to preserve Referential Equality to protect the subtree.
useRef for ConstantsSometimes useMemo is overkill.
If you need a value "Computed once, never changes":
// Stable across re-renders
const id = useRef(uuidv4()).current;
Cheaper than useMemo([], ...).
useCallbackuseCallback is often misunderstood.
It does NOT prevent function creation.
const fn = useCallback(() => {}, []) actually creates the arrow function () => {} Every Single Render.
It just discards the new one and returns the old one if deps didn't change.
So useCallback actually increases memory usage (it holds TWO function references: the old one and the new one to compare).
Its ONLY purpose is Referential Stability for React.memo or useEffect.
It does NOT save memory. It spends memory to save renders.
Performance optimization is an art of Trade-offs.
useMemo).React.memo).If you apply these blindly (Premature Optimization), you pay the cost (Memory, Complexity) without getting the benefit (Speed). In fact, you often get a slowdown.
Summary:
useMemo is not free. Don't use it for simple math. Use it only for Heavy Calculations or preserving Reference Equality for React.memo components. Premature optimization is the root of all evil.