🚀 Executive Summary
TL;DR: React’s ‘Forget’ compiler automates memoization, reducing the need for manual `useMemo` and `useCallback` hooks by handling referential equality issues during the build process. While not obsolete, these hooks will transition from daily use to specialized tools for advanced performance tuning and complex edge cases.
🎯 Key Takeaways
- JavaScript’s referential equality is the core reason for manual memoization in React, as new function/object references on re-renders trigger unnecessary child component updates.
- The React ‘Forget’ compiler analyzes component code during the build to automatically insert memoization, equivalent to `useMemo` and `useCallback`, based on dependency analysis.
- `useMemo` and `useCallback` will not be obsolete but will become advanced, surgical instruments for high-stakes optimizations, library authoring, and complex scenarios where the compiler’s automation isn’t sufficient.
React’s new ‘Forget’ compiler promises to handle memoization automatically, but don’t rush to delete your `useMemo` and `useCallback` hooks just yet. A senior engineer explains why these tools will evolve from daily chores into specialized instruments for complex performance tuning.
React ‘Forget’ is Coming. Should We Burn Our useMemo and useCallback Hooks?
I still have nightmares about a bug from last year. We had a dashboard with a massive, interactive data grid—the kind of component that makes product managers drool and engineers weep. It was dog-slow. Clicks took seconds to register. Typing in a filter input felt like wading through molasses. A junior dev, trying to be helpful, had wrapped nearly every function and object in `useCallback` and `useMemo`. The problem? He missed one single function passed down five levels deep. Just one. That one new function reference on every render was causing a catastrophic cascade, re-rendering hundreds of cells needlessly. We spent two days tracing prop diffs to find it. That’s the world we live in: memoization is both our greatest performance tool and our most tedious foot-gun.
So, Why Do We Even Have This Problem?
Before we talk about the fancy new compiler, let’s get back to basics. Why do we even need to manually memoize things in React? It boils down to one simple concept in JavaScript: referential equality.
Every time a React component renders, any functions or objects defined inside it are brand new. They have a new “address” in memory. To React, `() => {}` from the last render is not the same as `() => {}` from the current render, even if the code is identical.
When you pass these new functions or objects as props to a child component (especially one wrapped in `React.memo`), the child sees a “changed” prop and re-renders. Most of the time, this is a wasted effort. `useCallback` and `useMemo` are just manual ways of telling React: “Hey, hold onto the memory address for this thing and only give me a new one if its dependencies have actually changed.” It’s a low-level, error-prone task we’ve all been forced to manage.
Enter React ‘Forget’: The Automated Fix
The upcoming React ‘Forget’ compiler is a game-changer. It analyzes your component’s code during the build process and automatically inserts the equivalent of `useMemo` and `useCallback` where they’re needed. It’s smart enough to understand dependency arrays and figure out when values are stable between renders. The goal is to let us write simple, clean code without constantly worrying about performance cliffs caused by reference changes.
The big question everyone’s asking is: does this make our manual hooks completely obsolete? My take: No, but their role is about to change dramatically. Here’s how I’m advising my team to think about it.
Approach 1: The Pragmatic “Don’t Touch Production” Stance
Let’s be real: we have deadlines to meet and production servers like `prod-api-gateway-01` to keep stable. The compiler is new technology. For the next year or two, my primary advice is simple: don’t go on a `useMemo`-deleting rampage in your established, critical codebases.
Let the existing, hand-tuned memoization sit. It works. For new components, or during planned refactors, start writing code as if the compiler is there. Write the naive, simple version first. If you hit a performance bottleneck, profile it. Only then should you consider if a manual override is needed. This is about stability over novelty.
Warning: A premature “cleanup” PR that just deletes dozens of `useMemo` and `useCallback` hooks across a large app is a red flag. It introduces high risk for performance regressions for very little reward until the compiler is battle-tested and universally adopted.
Approach 2: The Proactive “Embrace the Future” Refactor
On the flip side, you can’t ignore the future. For new projects, internal tools, or non-critical feature branches, this is the perfect time to change your habits. The goal is to trust the compiler and write cleaner, more readable code.
Here’s what that looks like in practice.
Before ‘Forget’ (Manual Memoization)
function UserProfile({ userId, theme }) {
const userOptions = useMemo(() => ({
id: userId,
theme: theme,
showAvatars: true,
}), [userId, theme]);
const handleFollow = useCallback(() => {
// API call to follow user
console.log(`Following user ${userId}`);
}, [userId]);
return <ProfileHeader options={userOptions} onFollow={handleFollow} />;
}
After ‘Forget’ (Compiler-Friendly Code)
function UserProfile({ userId, theme }) {
// The compiler will memoize this object automatically
const userOptions = {
id: userId,
theme: theme,
showAvatars: true,
};
// The compiler will memoize this function automatically
const handleFollow = () => {
// API call to follow user
console.log(`Following user ${userId}`);
};
return <ProfileHeader options={userOptions} onFollow={handleFollow} />;
}
The second example is objectively easier to read and maintain. The cognitive overhead is gone. This is the style we should be striving for in new code.
Approach 3: The “Know Your Tools” Deep Dive
This is the “nuclear option” and where I believe these hooks will live on. `useMemo` and `useCallback` won’t be obsolete; they’ll become what they always should have been: advanced tools for specific, high-stakes optimizations.
The compiler will be fantastic, but it won’t be perfect. There will be edge cases it can’t reason about, especially involving complex data transformations or interactions with external, non-React systems. Think about:
- Optimizing a third-party library you are publishing. You need to provide a rock-solid, stable API, and explicitly memoizing can guarantee that.
- Expensive calculations inside a component that renders hundreds of times a second (e.g., a data visualization or a game).
- When you need to explicitly control the identity of a function or object to break a dependency cycle or manage a complex effect in `useEffect`.
In these scenarios, `useMemo` and `useCallback` become surgical instruments. You’ll use them rarely, but when you do, it will be for a very deliberate and justifiable reason, not just as a default best practice.
A Quick Comparison: Manual vs. Automated
| Aspect | Manual (useMemo/useCallback) | Automated (React ‘Forget’) |
| Developer Experience | Poor. High cognitive load, easy to make mistakes (e.g., missing dependency). | Excellent. Write natural code, compiler handles optimization. |
| Performance | Potentially optimal if done perfectly. Often sub-optimal due to human error. | Very good by default. Aims for “good enough” everywhere, preventing major cliffs. |
| Control | Absolute. You decide exactly what gets memoized and when. | Indirect. You trust the compiler’s heuristics, with potential escape hatches. |
| Best For | Legacy codebases, surgical performance tuning, library authors. | All new application code. The default for 99% of use cases. |
Final Thoughts
React ‘Forget’ is a massive quality-of-life improvement. It automates one of the most tedious and error-prone parts of writing performant React apps. But calling `useMemo` and `useCallback` obsolete is premature. They are simply being promoted from grunt work to a specialized role. Your job isn’t to forget how they work; it’s to get so good that you rarely have to use them, but you know exactly how to reach for them when the automated magic isn’t enough. And that, to me, is the mark of a senior engineer.
🤖 Frequently Asked Questions
âť“ Will React’s ‘Forget’ compiler make `useMemo` and `useCallback` completely obsolete?
No, `useMemo` and `useCallback` will not become obsolete. They will evolve into specialized tools for advanced performance tuning, complex edge cases, and library authoring, while the ‘Forget’ compiler handles most routine memoization automatically.
âť“ How does React ‘Forget’ compare to manual `useMemo` and `useCallback` for memoization?
React ‘Forget’ offers excellent developer experience by automating memoization, reducing cognitive load, and providing good default performance for 99% of use cases. Manual `useMemo`/`useCallback` provides absolute control and potentially optimal performance if done perfectly, but has poor developer experience due to high cognitive load and error proneness, making it best for legacy code or surgical optimizations.
âť“ What is a common implementation pitfall when transitioning to React ‘Forget’?
A common pitfall is prematurely deleting existing `useMemo` and `useCallback` hooks in established, critical codebases. This introduces high risk for performance regressions for minimal immediate reward until the ‘Forget’ compiler is battle-tested and widely adopted in production.
Leave a Reply