React 19.2: All New Features in the Third Major Release of 2025
Hello HaWkers, React 19.2 arrived in October 2025, marking the third significant release in the past year after React 19 in December 2024 and React 19.1 in June 2025.
Have you updated your projects yet? Let's explore the new features that promise to change how we build React applications.
React 19.2 Overview
React 19.2 continues the evolution of the async-first architecture introduced in React 19, bringing new primitives for rendering control and performance.
Main Additions
- Activity component - New primitive for organizing parts of your app
- useEffectEvent - Hook for events inside effects
- cacheSignal - Cache control for Server Components
- Performance Tracks - New profiling tool
- Partial Pre-rendering - Partial pre-rendering of your application
Activity Component
Activity is a new primitive that lets you break your app into "activities" that can be controlled and prioritized.
Basic Concept
import { Activity } from 'react';
function App() {
const [activeTab, setActiveTab] = useState('home');
return (
<div>
<TabBar activeTab={activeTab} onChange={setActiveTab} />
<Activity mode={activeTab === 'home' ? 'visible' : 'hidden'}>
<HomePage />
</Activity>
<Activity mode={activeTab === 'profile' ? 'visible' : 'hidden'}>
<ProfilePage />
</Activity>
<Activity mode={activeTab === 'settings' ? 'visible' : 'hidden'}>
<SettingsPage />
</Activity>
</div>
);
}Activity Modes
// visible - Renders and shows normally
<Activity mode="visible">
<Content />
</Activity>
// hidden - Maintains state but hides from DOM
<Activity mode="hidden">
<Content />
</Activity>
// Smooth transitions between states
function TabContent({ isActive, children }) {
return (
<Activity mode={isActive ? 'visible' : 'hidden'}>
{children}
</Activity>
);
}
Activity Benefits
1. State preservation:
Unlike conditional rendering, Activity preserves all component state when hidden.
// Problem: State lost when switching tabs
function OldApproach({ activeTab }) {
return (
<>
{activeTab === 'form' && <FormWithState />} {/* State reset */}
</>
);
}
// Solution: Activity preserves state
function NewApproach({ activeTab }) {
return (
<Activity mode={activeTab === 'form' ? 'visible' : 'hidden'}>
<FormWithState /> {/* State maintained */}
</Activity>
);
}2. Rendering prioritization:
React can prioritize visible activities over hidden ones.
// Visible activities have priority
<Activity mode="visible" priority="high">
<CriticalContent />
</Activity>
<Activity mode="hidden" priority="low">
<PreloadedContent />
</Activity>useEffectEvent
The new useEffectEvent hook solves a classic problem: using current values inside effects without causing re-execution.
The Problem
// Problem: Effect re-runs whenever onMessage changes
function Chat({ onMessage }) {
useEffect(() => {
const connection = connect();
connection.on('message', (msg) => {
onMessage(msg); // onMessage is new reference each render
});
return () => connection.disconnect();
}, [onMessage]); // Reconnects every render!
}The Solution
import { useEffectEvent } from 'react';
function Chat({ onMessage }) {
// Creates stable reference to callback
const onMessageEvent = useEffectEvent(onMessage);
useEffect(() => {
const connection = connect();
connection.on('message', (msg) => {
onMessageEvent(msg); // Always uses most recent version
});
return () => connection.disconnect();
}, []); // No dependencies, doesn't reconnect!
}
Practical Use Cases
// Logging with current values
function ProductPage({ productId, analytics }) {
const logVisit = useEffectEvent(() => {
analytics.logVisit(productId); // Always uses current productId
});
useEffect(() => {
logVisit();
}, []);
return <Product id={productId} />;
}
// Timer with updated callback
function Timer({ onTick }) {
const handleTick = useEffectEvent(onTick);
useEffect(() => {
const id = setInterval(() => {
handleTick();
}, 1000);
return () => clearInterval(id);
}, []);
}cacheSignal
cacheSignal offers fine-grained control over Server Components cache.
Basic Usage
import { cacheSignal } from 'react';
async function ProductList() {
// Signal for cache invalidation
const signal = cacheSignal();
const products = await fetchProducts({ signal });
return (
<ul>
{products.map(p => (
<li key={p.id}>{p.name}</li>
))}
</ul>
);
}Manual Invalidation
// Server Action to invalidate cache
'use server';
import { invalidateCache } from 'react';
export async function updateProduct(id, data) {
await db.products.update(id, data);
// Invalidates cache for components using this signal
invalidateCache('products');
}Partial Pre-rendering
The most impactful feature in React 19.2 is Partial Pre-rendering, which allows pre-rendering static parts of your application.
How It Works
// Static layout pre-rendered
function Layout({ children }) {
return (
<html>
<head>
<title>My App</title>
</head>
<body>
<Header /> {/* Static - pre-rendered */}
<Sidebar /> {/* Static - pre-rendered */}
<Suspense fallback={<Loading />}>
{children} {/* Dynamic - rendered after */}
</Suspense>
<Footer /> {/* Static - pre-rendered */}
</body>
</html>
);
}
Performance Benefits
Traditional flow:
- Request arrives
- Server renders everything
- Sends complete HTML
- User sees content
With Partial Pre-rendering:
- Request arrives
- Server sends pre-rendered shell immediately
- User sees structure instantly
- Dynamic content loads progressively
// Defining static vs dynamic parts
export default function Page() {
return (
<>
{/* These parts come from CDN instantly */}
<Navigation />
<Hero />
{/* This part is rendered on demand */}
<Suspense fallback={<ProductSkeleton />}>
<ProductRecommendations />
</Suspense>
{/* Static again */}
<Footer />
</>
);
}Performance Tracks
New tool for detailed performance profiling.
DevTools Integration
import { startTrack, endTrack } from 'react';
function ExpensiveComponent() {
startTrack('ExpensiveComponent:render');
const result = expensiveCalculation();
endTrack('ExpensiveComponent:render');
return <div>{result}</div>;
}Visualization in React DevTools
The Profiler now shows:
- Render time per track
- Dependency cascade
- Server Components vs Client Components impact
- Cache hit/miss metrics
React Compiler Improvements
The React Compiler introduced in React 19 received significant improvements.
Enhanced Automatic Memoization
// React Compiler now optimizes automatically
function ProductCard({ product, onAddToCart }) {
// Before: Needed useMemo/useCallback
// Now: Compiler optimizes automatically
const formattedPrice = formatCurrency(product.price);
const handleClick = () => onAddToCart(product.id);
return (
<div onClick={handleClick}>
<h3>{product.name}</h3>
<p>{formattedPrice}</p>
</div>
);
}
Migrating to React 19.2
Updating Dependencies
npm install react@19.2.0 react-dom@19.2.0Checking Compatibility
// Check version
import { version } from 'react';
console.log(version); // "19.2.0"
// Check if Activity is available
const hasActivity = typeof Activity !== 'undefined';Enabling New Features
// next.config.js (for Next.js)
module.exports = {
experimental: {
ppr: true, // Partial Pre-rendering
reactCompiler: true,
},
};Version Comparison
| Feature | React 19 | React 19.1 | React 19.2 |
|---|---|---|---|
| Server Components | Stable | Stable | Stable |
| Actions API | New | Improved | Improved |
| use() API | New | Stable | Stable |
| Compiler | Beta | Stable | Improved |
| Activity | - | - | New |
| useEffectEvent | - | - | New |
| Partial Pre-rendering | - | Experimental | Stable |
Best Practices
When to Use Activity
// GOOD: Tabs with complex state
<Activity mode={activeTab === 'editor' ? 'visible' : 'hidden'}>
<CodeEditor />
</Activity>
// GOOD: Modals that preserve state
<Activity mode={isModalOpen ? 'visible' : 'hidden'}>
<Modal>
<ComplexForm />
</Modal>
</Activity>
// AVOID: Simple stateless content
// Use normal conditional rendering
{showContent && <SimpleContent />}When to Use useEffectEvent
// GOOD: Callbacks in long-running effects
const handleMessage = useEffectEvent(onMessage);
// GOOD: Analytics and logging
const logEvent = useEffectEvent((event) => analytics.log(event));
// AVOID: Replacing useCallback for normal event handlers
// useCallback is still appropriate for component props
Conclusion
React 19.2 continues React's evolution towards a more efficient and flexible architecture. Activity and useEffectEvent solve real development problems, while Partial Pre-rendering offers significant performance gains.
The recommendation is to start experimenting with these features in new projects or isolated parts of existing projects before a complete migration.
If you want to deepen your knowledge in React and modern JavaScript, I recommend checking out another article: ECMAScript 2025: All New Features where you'll discover JavaScript features that complement React 19.2.
Let's go! 🦅
🎯 Join Developers Who Are Evolving
Thousands of developers already use our material to accelerate their studies and achieve better positions in the market.
Why invest in structured knowledge?
Learning in an organized way with practical examples makes all the difference in your journey as a developer.
Start now:
- 1x of $4.90 on card
- or $4.90 at sight
"Excellent material for those who want to go deeper!" - John, Developer

