React 19.3

React 19.3 is now available on npm!

Last year, we shared View Transitions and Fragment Refs as new experimental APIs coming to React. We’re excited to announce that both of these are now stable in React 19.3!

In this post, we’ll go over how they work, and also cover some other notable changes in this release.


New React Features

View Transitions

The new <ViewTransition> component lets you animate elements as they enter, exit, move, or resize using the browser’s View Transition API. We shared it as an experimental API last year, and in 19.3 it’s stable and ready to use.

To animate part of your UI, wrap it in <ViewTransition>:

import { ViewTransition } from 'react';

{isShowing && (

<ViewTransition>

<Component />

</ViewTransition>

)}

Now, whenever an update marked as a Transition changes the child component’s style, or causes the ViewTransition to be mounted or unmounted, React will animate that update.

React chooses which animation to run based on how the tree changed:

  • enter: the <ViewTransition> is added.

  • exit: the <ViewTransition> is removed.

  • update: the children of a <ViewTransition> change style or content.

  • share: a named <ViewTransition> is removed in one place and added in another.

Note that updates not marked as Transitions don’t trigger animations, as those are meant to be urgent and reflected immediately in the UI. State updates inside of startTransition, a <Suspense> reveal, or an update from useDeferredValue all cause a View Transition to animate.

Here’s a simple example of an enter/exit animation:

Fork

import { ViewTransition, useState, startTransition } from 'react';
import { Video } from './Video';
import videos from './data';

export default function Component() {
const [showItem, setShowItem] = useState(false);

return (
<>
<button
onClick={() => {
startTransition(() => {
setShowItem((prev) => !prev);
});
}}>
{showItem ? '➖' : '➕'}
</button>

{showItem && (
<ViewTransition>
<Video video={videos[0]} />
</ViewTransition>
)}
</>
);
}

By default, <ViewTransition> animates with a smooth cross-fade. You can customize each kind of animation by passing a View Transition Class and defining the animation in CSS, or you can use the Web Animations API to trigger animations imperatively with the event props (onEnter, onExit, onShare, onUpdate).

Currently, <ViewTransition> only works in the DOM. We’re working on support for React Native and other platforms.

For more, see the <ViewTransition> docs.


addTransitionType

Sometimes, you’ll want to customize which animation is used for the same state update. For example, navigating a carousel forward to the third slide should animate the slides right-to-left, while navigating it backward should animate them left-to-right, even though both actions set the currentSlide to 3.

You can customize the animation for a given View Transition by calling addTransitionType alongside the state update. This lets you add more information about the cause of a particular transition:

function nextSlide() {

startTransition(() => {

addTransitionType('next');

setCurrentSlide(c => c + 1);

});

}

function previousSlide() {

startTransition(() => {

addTransitionType('previous');

setCurrentSlide(c => c - 1);

});

}

Then, you can specify different animations based on that transition type:

<ViewTransition

enter={{

'next': 'from-right',

'previous': 'from-left',

}}

exit={{

'next': 'to-left',

'previous': 'to-right',

}}

>

<Page />

</ViewTransition>

Here’s an example:

Fork

import {
ViewTransition,
addTransitionType,
useState,
startTransition,
Fragment
} from 'react';
import { Video } from './Video';
import videos from './data';
import './animations.css';

export default function Component() {
const [selected, setSelected] = useState(0)
const video = videos[selected];

return (
<>
<div className="button-container">
<button
onClick={() => {
startTransition(() => {
addTransitionType('previous');
setSelected(c => c > 0 ? c - 1 : videos.length - 1 )
});
}}>
⬅️
</button>
<button
onClick={() => {
startTransition(() => {
addTransitionType('next');
setSelected(c => c + 1 < videos.length ? c + 1 : 0)
});
}}>
➡️
</button>
</div>

<ViewTransition
key={video.id}
enter={{
'next': 'from-right',
'previous': 'from-left'
}}
exit={{
'next': 'to-left',
'previous': 'to-right'
}}
>
<Video video={video} />
</ViewTransition>
</>
);
}

React also adds every Transition Type to the element as a browser view transition type, so you can scope animations in CSS with :active-view-transition-type(...).

To learn more, see the addTransitionType docs.


(节选)

原文:React Blog|React 19.3,2026-09-09