Ce qui se passe
React 19.3 est disponible sur npm depuis le 9 septembre. Les deux API
présentées comme expérimentales en avril 2025 — View Transitions et
Fragment Refs — y passent stables. S'y ajoutent browser() côté react-dom,
le support des Trusted Types, et un <Context> rendu directement depuis un
Server Component.
Animer sans bibliothèque
<ViewTransition> s'appuie sur la View Transition API du
navigateur
pour animer ce qui entre, sort, se déplace ou change de taille :
import { ViewTransition } from 'react';
{isShowing && (
<ViewTransition>
<Component />
</ViewTransition>
)}Le piège est dans le déclencheur. Rien ne s'anime en dehors d'une Transition :
startTransition, useDeferredValue, ou une frontière <Suspense> qui se
résout. Une mise à jour d'état ordinaire ne produit aucune animation — et c'est
la première chose à vérifier quand « ça ne marche pas ».
Quatre types d'animation existent : enter, exit, update (le style ou le
contenu change) et share (le même name réapparaît ailleurs dans l'arbre).
Pour distinguer deux sens de navigation, addTransitionType marque la transition,
et le nom devient adressable côté CSS :
import { startTransition, addTransitionType } from 'react';
function nextSlide() {
startTransition(() => {
addTransitionType('next');
setCurrentSlide(c => c + 1);
});
}
<ViewTransition
enter={{ next: 'from-right', previous: 'from-left' }}
exit={{ next: 'to-left', previous: 'to-right' }}
>
<Page />
</ViewTransition>Le sélecteur :active-view-transition-type(next) permet de faire la même chose
en CSS pur.
Une ref sur un Fragment
Poser une ref sur un <Fragment> donne un FragmentInstance, qui expose
les opérations DOM d'un groupe d'enfants sans nœud enveloppant :
| Domaine | Méthodes |
|---|---|
| Événements | addEventListener, removeEventListener, dispatchEvent |
| Focus | focus, focusLast, blur |
| Observers | observeUsing, unobserveUsing |
| Mesure et position | getClientRects, getRootNode, compareDocumentPosition, scrollIntoView |
Concrètement : brancher un IntersectionObserver sur une liste d'éléments ne
demande plus la <div> de trop qui cassait la grille ou le flex parent.
Marquer un composant « client seulement »
Un composant qui lit localStorage ou le fuseau horaire local n'a rien à produire
sur le serveur. On s'en sortait avec un état monté dans un effet, ou un
typeof window !== 'undefined'. React 19.3 en fait une API :
import { use } from 'react';
import { browser } from 'react-dom';
function TimeZone() {
use(browser());
return <p>{new Intl.DateTimeFormat().resolvedOptions().timeZone}</p>;
}Sur le serveur, l'appel suspend et c'est le fallback du <Suspense> le plus
proche qui part dans le HTML ; sur le client, il ne suspend pas. Comme tout appel
à use, il s'écrit dans une condition ou après un retour anticipé — de quoi ne
sortir du rendu serveur que dans certains cas.
Ce que ça change aussi
Trusted Types. React convertissait systématiquement les valeurs en chaînes
('' + value) avant de les passer aux API du DOM, ce qui retransformait un objet
TrustedHTML en chaîne brute que le navigateur rejetait. Il les passe désormais
sans coercition : sous
Content-Security-Policy: require-trusted-types-for 'script', vos politiques de
désinfection fonctionnent enfin comme prévu.
Context dans les Server Components. Un Server Component peut importer un
contexte depuis un module 'use client' et le fournir directement, sans le
composant Provider intermédiaire qu'il fallait écrire jusqu'ici.
À retenir
Aucune rupture annoncée. Le vrai arbitrage est ailleurs : les View Transitions reposent sur une API du navigateur dont la couverture n'est pas uniforme, il faut donc que l'absence d'animation reste un état acceptable, pas un écran cassé.
Le changelog contient par ailleurs de quoi retirer des contournements : onReset
émis après une Server Action, le submitter inclus dans les événements submit,
fetchPriority sur les ressources module, et une série de correctifs de Fast
Refresh.
Source : React 19.3