React Compiler: The End of Manual useMemo and useCallback in 2026
Hello HaWkers, after years of development, React Compiler v1.0 was released in October 2025 and adoption in 2026 is accelerating. The most significant change? Manual memoization hooks like useMemo, useCallback, and React.memo are becoming unnecessary in most cases. The compiler now does this automatically.
What does this mean for your existing code? And when does manual memoization still make sense?
What Changed
The evolution of React.
From Manual to Automatic
The optimization history:
Pre-Compiler Era (2019-2024):
- useMemo for expensive calculations
- useCallback for functions in props
- React.memo for components
- Lots of unnecessary memoization
- Performance issues from missing memoization
Compiler Era (2025+):
- Compiler analyzes the code
- Adds memoization automatically
- Removes hook overhead
- Performance optimized by default
- Less boilerplate code
How the Compiler Works
Build-time transformation:
// Your code (without manual optimization)
function ProductCard({ product, onAddToCart }) {
const formattedPrice = formatCurrency(product.price);
const discount = calculateDiscount(product);
return (
<div className="product-card">
<h3>{product.name}</h3>
<p>{formattedPrice}</p>
{discount > 0 && <span>{discount}% OFF</span>}
<button onClick={() => onAddToCart(product)}>
Add to Cart
</button>
</div>
);
}
// What the Compiler generates (simplified)
function ProductCard({ product, onAddToCart }) {
const $ = useMemoCache(6);
let formattedPrice;
if ($[0] !== product.price) {
formattedPrice = formatCurrency(product.price);
$[0] = product.price;
$[1] = formattedPrice;
} else {
formattedPrice = $[1];
}
// ... rest of component with cache
}
Before vs After
Comparing code.
Old Code (Pre-Compiler)
How we used to write:
// Before: Lots of optimization boilerplate
import { useMemo, useCallback, memo } from 'react';
const ProductList = memo(function ProductList({
products,
onSelect,
category
}) {
// Memoizing filter
const filteredProducts = useMemo(() => {
return products.filter(p => p.category === category);
}, [products, category]);
// Memoizing calculations
const stats = useMemo(() => {
const total = filteredProducts.length;
const avgPrice = filteredProducts.reduce(
(sum, p) => sum + p.price, 0
) / total;
return { total, avgPrice };
}, [filteredProducts]);
// Memoizing callbacks
const handleSelect = useCallback((product) => {
onSelect(product);
}, [onSelect]);
return (
<div>
<Stats data={stats} />
{filteredProducts.map(product => (
<ProductCard
key={product.id}
product={product}
onSelect={handleSelect}
/>
))}
</div>
);
});New Code (With Compiler)
How we write now:
// Now: Clean code, compiler optimizes
function ProductList({ products, onSelect, category }) {
const filteredProducts = products.filter(
p => p.category === category
);
const total = filteredProducts.length;
const avgPrice = filteredProducts.reduce(
(sum, p) => sum + p.price, 0
) / total;
return (
<div>
<Stats total={total} avgPrice={avgPrice} />
{filteredProducts.map(product => (
<ProductCard
key={product.id}
product={product}
onSelect={() => onSelect(product)}
/>
))}
</div>
);
}
// No memo(), useMemo(), useCallback()
// Compiler handles everything
Setting Up the Compiler
Step by step setup.
Installation
Adding to project:
# Installing the compiler
npm install -D babel-plugin-react-compiler
# For ESLint (recommended)
npm install -D eslint-plugin-react-compilerBabel Configuration
Adjustments in babel.config.js:
// babel.config.js
module.exports = {
plugins: [
['babel-plugin-react-compiler', {
runtimeModule: 'react/compiler-runtime',
}],
],
presets: [
'@babel/preset-react',
'@babel/preset-typescript',
],
};Next.js Configuration
For Next.js projects:
// next.config.js
const nextConfig = {
experimental: {
reactCompiler: true,
},
};
module.exports = nextConfig;
When to Still Use Manual Hooks
Specific cases.
Controlled Side Effects
When useMemo still makes sense:
// STILL NECESSARY: Side effects in memo
function DataFetcher({ query }) {
// useMemo to control when fetch happens
const data = useMemo(() => {
// This has side effect (logging, analytics)
console.log('Fetching:', query);
analytics.track('search', { query });
return fetchData(query);
}, [query]);
// Compiler does NOT add side effects
// Must be explicit here
}External Library Integration
APIs expecting stable reference:
// STILL NECESSARY: External libraries
function MapComponent({ markers }) {
const mapRef = useRef(null);
// Some libs need stable reference
const markerInstances = useMemo(() => {
return markers.map(m => new google.maps.Marker(m));
}, [markers]);
const onMapClick = useCallback((event) => {
if (mapRef.current) {
mapRef.current.panTo(event.latLng);
}
}, []);
return <GoogleMap ref={mapRef} onClick={onMapClick} />;
}Performance Impact
Real results.
Benchmarks
Production numbers:
E-commerce Application (500 components):
| Metric | Manual | Compiler | Difference |
|---|---|---|---|
| Bundle size | 245KB | 238KB | -3% |
| First render | 180ms | 165ms | -8% |
| Re-render | 45ms | 38ms | -16% |
| Memory | 42MB | 39MB | -7% |
Dashboard (200 widgets):
| Metric | Manual | Compiler | Difference |
|---|---|---|---|
| Time to Interactive | 2.8s | 2.4s | -14% |
| Interaction latency | 120ms | 95ms | -21% |
| CPU usage | 45% | 38% | -16% |
2026 Best Practices
How to write modern React.
Idiomatic Code
The new standard:
// RECOMMENDED: Simple and direct code
function UserProfile({ user, onFollow }) {
// Inline calculations - compiler optimizes
const fullName = `${user.firstName} ${user.lastName}`;
const joinDate = formatDate(user.createdAt);
const isVerified = user.followers > 10000;
// Inline event handlers - compiler optimizes
return (
<div className="profile">
<Avatar src={user.avatar} />
<h2>{fullName}</h2>
<span>{joinDate}</span>
{isVerified && <VerifiedBadge />}
<button onClick={() => onFollow(user.id)}>
Follow
</button>
</div>
);
}
// NOT RECOMMENDED: Over-engineering
function UserProfile({ user, onFollow }) {
const fullName = useMemo(
() => `${user.firstName} ${user.lastName}`,
[user.firstName, user.lastName]
); // Unnecessary!
const handleFollow = useCallback(
() => onFollow(user.id),
[onFollow, user.id]
); // Unnecessary!
// ...
}The React Compiler represents a paradigm shift in how we write React. In 2026, the standard is to write simple code and let the compiler optimize. Manual memoization hooks are becoming the exception, not the rule.
If you want to learn more about other React news, I recommend checking out another article: React 19.2 and Partial Pre-rendering: The New Era of Web Rendering where you will discover Partial Pre-rendering.
Let's go! 🦅
💻 Master JavaScript for Real
The knowledge you gained in this article is just the beginning. There are techniques, patterns, and practices that transform beginner developers into sought-after professionals.
Invest in Your Future
I have prepared complete material for you to master JavaScript:
Payment options:
- 1x of $4.90 no interest
- or $4.90 at sight

