This article is published in English.
Adopting React 19.2: Activity for Tabbed UIs and an Upgrade Checklist
How React 19.2's Activity keeps hidden tabs alive, where useEffectEvent and pre-rendering fit, and how to decide whether to upgrade and patch RSC apps now.
Tabs, wizards and off-screen lists share one failure: hide a panel with conditional rendering and it unmounts, taking scroll position, half-filled forms and fetched data with it. React 19.2 answers this with the Activity component. This guide applies Activity to a tab layout, then covers the rest of the release and a checklist for deciding when to upgrade.
What 19.2 is trying to fix
React now ships several releases a year, and 19.2 is not a rewrite. It targets old pain points: state lost on unmount, effect dependency headaches, and the trade-off between fast static pages and fresh data.
Activity: hiding UI without destroying it
Think of Activity as a smarter alternative to {condition && <Panel />}. It takes a mode prop with two values:
hiddenhides the children, unmounts their effects, and defers any updates until React has no higher-priority work left.visibleshows the children, mounts their effects again, and processes updates normally.
The important detail is what survives. Component state and the rendered tree are kept, so switching back is instant, but effects are cleaned up while hidden. Subscriptions, timers and polling therefore stop, which is usually what you want for a panel nobody is looking at.
The example below wraps a settings panel and a billing panel in their own Activity boundaries, and the activeTab prop decides which one is visible. Both panels keep their scroll position and form input when the user switches away.
// Preserve a tab's scroll position and form state
// even when the user switches away from it
import { unstable_Activity as Activity } from 'react';
function ProfileTabs({ activeTab }) {
return (
<>
<Activity mode={activeTab === 'settings' ? 'visible' : 'hidden'}>
<SettingsPanel />
</Activity>
<Activity mode={activeTab === 'billing' ? 'visible' : 'hidden'}>
<BillingPanel />
</Activity>
</>
);
}
One caveat: the snippet imports unstable_Activity, the name used in pre-release builds. In stable 19.2 the component is exported as Activity, so check the current docs and import it under that name when you upgrade.
Since nothing is torn down and rebuilt on each switch, navigation feels faster. The cost is memory: every hidden panel stays alive, so reserve Activity for screens users are likely to revisit rather than wrapping every route.
useEffectEvent: fresh values without re-running effects
If you have ever added a value to a dependency array just to satisfy the linter and then watched an effect fire when it should not, this hook is the fix. It lets an effect read the latest props and state through a separate function without that value triggering a re-run.
Here theme is read inside onConnected, so the connection depends only on roomId.
function ChatRoom({ roomId, theme }) {
const onConnected = useEffectEvent(() => {
showNotification('Connected!', theme); // always fresh theme
});
useEffect(() => {
const connection = createConnection(roomId);
connection.on('connected', () => onConnected());
return () => connection.disconnect();
}, [roomId]); // theme intentionally left out — and that's fine now
}
Note that the snippet omits the connection.connect() call a real implementation would need before returning the cleanup.
Partial pre-rendering in React DOM
Partial pre-rendering began as an experimental Next.js 14 feature, and with 19.2 the underlying capability is part of react-dom. React pre-renders the static shell of a page ahead of time, leaves holes where dynamic Suspense boundaries sit, and fills those holes per request. You get close to static-generation speed with server-rendered freshness. Our deeper look at React 19.2's SSR primitives, cacheSignal and PPR covers the APIs in detail.
Smaller additions worth knowing
- Chrome DevTools gains React-specific Performance tracks, so you can see which work React schedules as blocking, which as a transition, and so on.
cacheSignalfor React Server Components helps avoid redundant work tied to cached computations.- Improvements to SSR streaming aim at a faster time to interactive.
Security: patch RSC apps first
Critical vulnerabilities in React Server Components were disclosed in December 2025. Apps on React 19.0.0 through 19.2.2 that use RSC, including a default create-next-app setup, were exposed to remote code execution. If you run Server Components, update to a patched release right away; confirm the exact fixed versions in the official React and Next.js advisories, since follow-up patches were published.
Should your team upgrade now?
- Upgrade soon if you build complex SSR apps, ship UIs with many tabs or steps, or keep fighting effect dependency bugs.
- Upgrade carefully if you maintain a large legacy codebase: try the stricter hooks lint rules on a branch first and fix what they flag.
- Upgrade immediately regardless of features if you rely on Server Components and have not applied the security patches.
Wrapping up
19.2 is a quiet release that pays off in daily work: Activity changes how you think about retained state, useEffectEvent removes a class of dependency hacks, and pre-rendering narrows the gap between static and dynamic pages. Try them on one tabbed screen before rolling them out widely.