hydrateRoot
hydrateRoot
vous permet d’afficher des composants React dans un nœud DOM du navigateur dont le HTML a été préalablement généré par react-dom/server
.
const root = hydrateRoot(domNode, reactNode, options?)
Référence
hydrateRoot(domNode, reactNode, options?)
Appelez hydrateRoot
pour « attacher » React à du HTML existant préalablement généré par React dans un environnement serveur.
import { hydrateRoot } from 'react-dom/client';
const domNode = document.getElementById('root');
const root = hydrateRoot(domNode, reactNode);
React s’attachera au HTML existant à l’intérieur de domNode
, et prendra la main sur la gestion du DOM à l’intérieur. Une appli entièrement construite avec React n’aura généralement qu’un seul appel à hydrateRoot
, pour le composant racine.
Voir d’autres exemples ci-dessous.
Paramètres
-
domNode
: un élément DOM généré comme élément racine côté serveur. -
reactNode
: un nœud React utilisé pour afficher le HTML existant. Ce sera généralement un bout de JSX du genre<App />
, généré via une méthodereact-dom/server
telle querenderToPipeableStream(<App />)
. -
options
optionnelles : un objet avec des options pour la racine React.onRecoverableError
optionnel : fonction de rappel appelée lorsque React retombe automatiquement sur ses pieds suite à une erreur.identifierPrefix
optionnel : un préfixe textuel utilisé pour les ID générés paruseId
. Pratique pour éviter les conflits entre les ID au sein de racines multiples sur une même page. Doit être le même préfixe que celui utilisé côté serveur.
Valeur renvoyée
hydrateRoot
renvoie un objet avec deux méthodes : render
et unmount
.
Limitations
hydrateRoot()
s’attend à ce que le contenu affiché soit identique au contenu généré côté serveur. Vous devriez considérer tout écart comme un bug et le corriger.- En mode développement, React vous avertira de tout écart de correspondance durant l’hydratation. Vous n’avez aucune garantie que les différences d’attributs seront résolues. C’est important pour des raisons de performances parce que dans la plupart des applis, les écarts sont rares, aussi valider tout le balisage serait d’une lourdeur prohibitive.
- Vous n’aurez probablement qu’un seul appel à
hydrateRoot
dans votre appli. Si vous utilisez un framework, il le fait peut-être pour vous. - Si votre appli est entièrement côté client, sans HTML déjà généré par le serveur, appeler
hydrateRoot()
n’est pas autorisé. Utilisez plutôtcreateRoot()
.
root.render(reactNode)
Appelez root.render
pour mettre à jour un composant React au sein d’une racine React hydratée associée à un élément DOM du navigateur.
root.render(<App />);
React mettra à jour <App />
dans le root
hydraté.
Voir d’autres exemples ci-dessous.
Paramètres
reactNode
: un nœud React que vous souhaitez mettre à jour. Ce sera généralement un bout de JSX du genre<App />
, mais vous pouvez aussi passer un élément React créé aveccreateElement()
, une chaîne de caractères, un nombre,null
ouundefined
.
Valeur renvoyée
root.render
renvoie undefined
.
Limitations
- Si vous appelez
root.render
avant que la racine n’ait terminé son hydratation, React effacera tout le HTML produit par le serveur et basculera la racine entière vers un rendu côté client.
root.unmount()
Appelez root.unmount
pour détruire l’arborescence de rendu au sein d’une racine React.
root.unmount();
Une appli entièrement construite avec React n’appellera généralement pas root.unmount
.
C’est principalement utile si le nœud DOM de votre racine React (ou un de ses ancêtres) est susceptible d’être retiré du DOM par du code tiers. Imaginez par exemple une gestion d’onglet basée sur jQuery qui retire les onglets inactifs du DOM. Si un onglet est retiré, tout ce qu’il contient (y compris d’éventuelles racines React) sera également retiré du DOM. Dans un tel cas, vous devez dire à React de « cesser » de gérer le contenu de la racine retirée en appelant root.unmount
. Si vous ne le faisiez pas, les composants au sein de la racine retirée ne pourraient pas être nettoyés et libérer leurs ressources globales, telles que des abonnements.
Un appel à root.unmount
démontera tous les composants dans cette racine et « détachera » React du nœud DOM racine, y compris pour la gestion événementielle et les états de l’arbre.
Paramètres
root.unmount
ne prend aucun paramètre.
Returns
root.unmount
renvoie undefined
.
Limitations
-
Appeler
root.unmount
démontera tous les composants dans cette racine et « détachera » React du nœud DOM racine. -
Une fois que vous avez appelé
root.unmount
, vous ne pouvez plus rappelerroot.render
sur cette même racine. Tenter d’appelerroot.render
sur une racine démontée lèvera une erreur “Cannot update an unmounted root” (« Impossible de mettre à jour une racine démontée », NdT).
Utilisation
Hydrater du HTML généré côté serveur
Si le HTML de votre appli est généré par react-dom/server
, vous devez l’hydrater côté client.
import { hydrateRoot } from 'react-dom/client';
hydrateRoot(document.getElementById('root'), <App />);
Ça hydratera le HTML issu du serveur au sein du nœud DOM du navigateur en utilisant le composant React de votre appli. En général, vous ne le ferez qu’une fois au démarrage. Si vous utilisez un framework, il le fait peut-être pour vous sous le capot.
Pour hydrater votre appli, React « attachera » la logique de vos composants au HTML initial généré par le serveur. L’hydratation transforme cet instantané initial du HTML, issu du serveur, en une appli pleinement interactive s’exécutant dans le navigateur.
import './styles.css'; import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; hydrateRoot( document.getElementById('root'), <App /> );
Vous ne devriez pas avoir besoin de rappeler hydrateRoot
ou de l’appeler ailleurs. À partir de ce moment, React prendra la main sur le DOM de votre application. Pour mettre à jour l’interface utilisateur (UI), vos composants mettront plutôt à jour l’état.
Hydrater un document entier
Les applis entièrement construites avec React peuvent produire le document entier via leur JSX, y compris la balise <html>
:
function App() {
return (
<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/styles.css"></link>
<title>Mon appli</title>
</head>
<body>
<Router />
</body>
</html>
);
}
Pour hydrater le document entier, passez la variable globale document
comme premier argument dans votre appel à hydrateRoot
:
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(document, <App />);
Réduire au silence les erreurs d’hydratation incontournables
Si pour un élément spécifique, un attribut ou le contenu textuel s’avère inévitablement différent entre le serveur et le client (un horodatage, par exemple), vous pouvez choisir de réduire au silence l’avertissement d’écart d’hydratation.
Pour éviter les avertissements d’hydratation sur un élément spécifique, ajoutez-lui la prop suppressHydrationWarning={true}
:
export default function App() { return ( <h1 suppressHydrationWarning={true}> Date actuelle : {new Date().toLocaleDateString()} </h1> ); }
Ça ne fonctionne qu’à un niveau de profondeur, et c’est vraiment une échappatoire. N’en abusez pas. React ne rattrapera le coup que pour les contenus textuels, il risque donc de rester quelques incohérences jusqu’au prochain rendu.
Différencier les contenus côté client et côté serveur
Si vous différenciez volontairement l’affichage entre le côté serveur et le côté client, vous pouvez faire un rendu en deux temps. Les composants qui affichent un contenu différent côté client peuvent lire une variable d’état telle que isClient
, que vous pouvez mettre à true
dans un Effet :
import { useState, useEffect } from "react"; export default function App() { const [isClient, setIsClient] = useState(false); useEffect(() => { setIsClient(true); }, []); return ( <h1> {isClient ? 'Côté client' : 'Côté serveur'} </h1> ); }
De cette façon, la passe initiale de rendu afficher le même contenu que côté serveur, évitant toute incohérence ; mais une passe supplémentaire surviendra de façon synchrone juste après l’hydratation.
Mettre à jour un composant racine hydraté
Après que la racine a terminé l’hydratation, vous pouvez appeler root.render
pour mettre à jour le composant React racine. Contrairement à createRoot
, vous n’avez pas besoin de faire ça car le contenu initial était déjà présent dans le HTML.
Si vous appelez root.render
après l’hydratation, et que la structure de l’arbre de composants correspond à celle déjà en place, React préservera l’état. Voyez comme vous pouvez taper quelque chose dans le champ, ce qui montre bien que les mises à jour issues d’appels répétés à render
ne sont pas destructrices :
import { hydrateRoot } from 'react-dom/client'; import './styles.css'; import App from './App.js'; const root = hydrateRoot( document.getElementById('root'), <App counter={0} /> ); let i = 0; setInterval(() => { root.render(<App counter={i} />); i++; }, 1000);
Il est toutefois rare d’appeler root.render
sur une racine hydratée. En général, vos composants mettront plutôt à jour l’état.