React 19.3 Ships Stable ViewTransition and Fragment Refs
React 19.3.0 shipped on September 9, 2026. Two APIs that have spent well over
a year behind the canary channel — <ViewTransition> and Fragment refs — are now
in a stable minor, along with a new react-dom API called browser() and an
opt-in Trusted Types integration. Nothing here is breaking; it is a minor on the
19.x line.
The practical headline for anyone building on Next.js: the animation APIs you
could previously only reach through the App Router's canary React are now
ordinary stable React. Next.js 16.3.4 declares a react peer range of
^18.2.0 || ^19.0.0, so 19.3.0 satisfies it without any override.
ViewTransition and addTransitionType
<ViewTransition> wraps React's concurrent rendering around the browser's
View Transitions API.
You give two elements on different screens the same name and the browser
animates between their old and new positions instead of cutting.
The important constraint is what activates it. <ViewTransition> animations fire
from Transitions, <Suspense> reveals and useDeferredValue — a plain
setState does not trigger one. In Next.js, route navigations are transitions,
so the animations activate on navigation with no wiring. addTransitionType
ships alongside it, letting you tag a transition (forward vs. back, say) and
branch your CSS on it.
The clearest evidence that this is a real status change is in Next.js's own
documentation. The view-transitions guide on the v16.3.4 tag reads:
View transitions work in the App Router with no configuration. The App Router uses React canary releases, which contain all stable React 19 changes as well as newer features like
ViewTransition. You do not need to installreact@canaryyourself.
The same file on
canary
now reads: "React 19.3 includes the <ViewTransition> component and
addTransitionType API used in this guide." The canary caveat is gone. If you
are on the Pages Router, or on plain React outside Next.js, this is the release
that opens the API to you.
One browser note carried over from the Next.js guide: React's integration relies
on transition types and view-transition-class, which need Chromium 125+ and
recent Safari and Firefox. Without support the app works normally, it just does
not animate.
Fragment refs
The second stable feature is smaller but removes a genuinely annoying pattern.
You can now pass a ref to a Fragment and get back a FragmentInstance that
operates on the fragment's first-level DOM children — no wrapper <div> added
purely to hang a ref on.
FragmentInstance implements:
addEventListener/removeEventListener/dispatchEvent— across all first-level DOM childrenfocus/focusLast/blur— searching all nested children depth-first, not just direct childrenobserveUsing/unobserveUsing— attach or detach anIntersectionObserverorResizeObserver
focus() is the one worth noticing: unlike element.focus(), it walks the
subtree until it finds something focusable, which is exactly the behaviour every
hand-rolled focus-management helper has been reimplementing.
There is a syntax caveat. You cannot use the <>...</> shorthand with a ref —
import Fragment explicitly:
import { Fragment, useRef } from 'react'
const ref = useRef(null)
return <Fragment ref={ref}>{children}</Fragment>
browser(): marking a subtree browser-only
react-dom gains browser(), used inside use():
import { use } from 'react'
import { browser } from 'react-dom'
function Chart() {
use(browser('Needs ResizeObserver.'))
return <ExpensiveCanvas />
}
During server rendering this stops the component and leaves the nearest
<Suspense> fallback in place; in the browser use(browser()) returns
undefined and the component renders normally. Unlike the usual
useEffect-plus-state dance, it is not reported as a recoverable hydration
error. Three caveats from the reference: it must sit inside a <Suspense>
boundary or the server render fails, in an RSC app it must be called from a
Client Component, and calling browser() without passing it to use() does
nothing. A matching onBrowserBailout option on the react-dom/server APIs lets
you observe which subtrees deferred.
The change you get for free
Buried under "Notable changes" is one that needs no code:
Transitions now render independently instead of being entangled into a single render, so a slow transition no longer holds up unrelated ones.
That is #37290. If you have ever watched one slow server response stall an unrelated piece of UI, this is the fix, and it pairs directly with the prefetching work in Next.js 16.3's Instant Navigations.
Also landing: Trusted Types API integration
(#35816), a DEV-only warning when
a component looks like it was unblocked by calling use() conditionally, and a
long run of Fast Refresh, Activity and Server Components fixes.
Upgrading
npm install react@19.3.0 react-dom@19.3.0
Read the release notes rather than the summaries — the 19.3.0 CHANGELOG entry and the GitHub release are the primary sources for everything above.
Thinking about adding view transitions to an existing App Router codebase, or unsure whether your React version is the vendored one or the one in your lockfile? Get in touch — auditing and upgrading Next.js applications is what we do.