createRoot
createRoot
vous permet de créer une racine de rendu pour afficher vos composants React dans un nœud DOM du navigateur.
const root = createRoot(domNode, options?)
Référence
createRoot(domNode, options?)
Appelez createRoot
pour créer une racine de rendu React afin d’afficher du contenu dans un élément DOM du navigateur.
import { createRoot } from 'react-dom/client';
const domNode = document.getElementById('root');
const root = createRoot(domNode);
React créera une racine de rendu associée au domNode
, puis prendra la main sur la gestion de son DOM. Une fois la racine créée, vous devrez appeler root.render
pour afficher un composant React à l’intérieur :
root.render(<App />);
Une appli entièrement construite en React n’aura généralement qu’un appel à createRoot
pour son composant racine. Une page qui « saupoudre » du React dans certaines de ses parties peut avoir autant de racines distinctes que nécessaire.
Voir d’autres exemples ci-dessous.
Paramètres
-
domNode
: un élément DOM. React créera une racine de rendu pour cet élément DOM et vous permettra d’appeler des méthodes sur cette racine, telles querender
pour afficher le contenu produit par React. -
options
optionnelles : un objet avec des options pour la racine React.- Canary uniquement
onCaughtError
optionelle : fonction de rappel appelée lorsque React capture une erreur au sein d’un Périmètre d’Erreur. Appelée avec l’error
capturée par le Périmètre d’Erreur, et un objeterrorInfo
contenant lacomponentStack
. - Canary uniquement
onUncaughtError
optionnelle : fonction de rappel appelée lorsqu’une erreur est levée sans être capturée par un Périmètre d’Erreur. Appelée avec l’error
levée par React et un objeterrorInfo
contenant lacomponentStack
. onRecoverableError
optionnelle : fonction de rappel appelée lorsque React retombe automatiquement sur ses pieds suite à une erreur. Appelée avec l’error
levée par React et un objeterrorInfo
contenant lacomponentStack
. Certaines de ces erreurs peuvent exposer leur cause originelle danserror.cause
.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.
- Canary uniquement
Valeur renvoyée
createRoot
renvoie un objet avec deux méthodes : render
et unmount
.
Limitations
- Si votre appli bénéficie d’un premier rendu côté serveur, vous ne pourrez pas utiliser
createRoot()
: utilisez plutôthydrateRoot()
. - Vous n’aurez probablement qu’un seul appel à
createRoot
dans votre appli. Si vous utilisez un framework, il le fait peut-être pour vous. - Lorsque vous souhaitez afficher un bout de JSX dans une autre partie du DOM, une partie qui n’est pas un enfant de votre composant (par exemple pour une boîte de dialogue modale ou une infobulle), utilisez
createPortal
plutôt quecreateRoot
.
root.render(reactNode)
Appelez root.render
pour afficher un bout de JSX (un « nœud React ») dans le nœud DOM du navigateur associé à la racine React.
root.render(<App />);
React affichera <App />
dans le root
, et prendra la main sur la gestion du DOM à l’intérieur.
Voir d’autres exemples ci-dessous.
Paramètres
reactNode
: un nœud React que vous souhaitez afficher. 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
-
La première fois que vous appellez
root.render
, React videra tout le HTML existant au sein de la racine avant de faire le rendu du composant React à l’intérieur -
Si le nœud DOM de votre racine contient du HTML généré par React côté serveur ou lors du build, utilisez plutôt
hydrateRoot()
, qui se contentera d’attacher les gestionnaires d’événements au HTML existant. -
Si vous appelez
render
sur la même racine plusieurs fois, React mettra à jour le DOM si nécessaire pour refléter le dernier JSX que vous lui avez passé. React décidera quelles parties du DOM réutiliser et lesquelles nécessitent une création à froid en « examinant la correspondance » entre l’arbre React et celui du précédent rendu. Appelerrender
à nouveau sur la même racine est similaire à un appel de fonctionset
sur le composant racine : React évite les mises à jour DOM superflues.
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.
Valeur renvoyée
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). En revanche, vous pouvez créer une nouvelle racine pour le même nœud DOM une fois la racine précédente pour ce nœud démontée.
Utilisation
Afficher une appli entièrement construite avec React
Si votre appli est entièrement construite avec React, créez une racine unique pour l’appli complète.
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
En général, vous n’aurez besoin de ce code qu’une fois, au démarrage. Il va :
- Trouver le nœud DOM du navigateur défini dans votre HTML.
- Afficher le composant React de votre appli à l’intérieur.
import { createRoot } from 'react-dom/client'; import App from './App.js'; import './styles.css'; const root = createRoot(document.getElementById('root')); root.render(<App />);
Si votre appli est entièrement construite avec React, vous ne devriez pas avoir besoin de créer davantage de racines, ni de rappeler root.render
.
À partir de là, React gèrera le DOM de votre appli entière. Pour ajouter d’autres composants, imbriquez-les dans le composant App
. Si vous avez besoin de mettre à jour l’interface utilisateur (UI), chaque composant peut le faire en utilisant l’état. Si vous souhaitez afficher du contenu complémentaire (comme une boîte de dialogue modale ou une infobulle) hors du nœud DOM, affichez-le dans un portail.
Afficher une page partiellement construite avec React
Si votre page n’est pas entièrement construite avec React, vous pouvez appeler createRoot
plusieurs fois, pour créer une racine de rendu pour chaque bloc d’UI géré par React. Vous pouvez alors afficher les contenus de votre choix dans chaque racine en appelantroot.render
.
Dans l’exemple ci-dessous, deux composants React distincts sont affichés dans deux nœuds DOM définis dans le fichier index.html
:
import './styles.css'; import { createRoot } from 'react-dom/client'; import { Comments, Navigation } from './Components.js'; const navDomNode = document.getElementById('navigation'); const navRoot = createRoot(navDomNode); navRoot.render(<Navigation />); const commentDomNode = document.getElementById('comments'); const commentRoot = createRoot(commentDomNode); commentRoot.render(<Comments />);
Vous pourriez aussi créer un nouveau nœud DOM avec document.createElement()
et l’ajouter manuellement au document.
const domNode = document.createElement('div');
const root = createRoot(domNode);
root.render(<Comment />);
document.body.appendChild(domNode); // Vous pouvez l’ajouter où bon vous semble
Pour retirer l’arbre React d’un nœud DOM et en nettoyer les ressources, appelez root.unmount
.
root.unmount();
C’est surtout utile pour les composants React figurant au sein d’une appli écrite avec un autre framework.
Mettre à jour un composant racine
Vous pouvez appeler render
plus d’une fois sur la même racine. Tant 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 { createRoot } from 'react-dom/client'; import './styles.css'; import App from './App.js'; const root = createRoot(document.getElementById('root')); let i = 0; setInterval(() => { root.render(<App counter={i} />); i++; }, 1000);
Il est toutefois rare d’appeler render
plusieurs fois. En général, vos composants mettront plutôt à jour l’état.
Afficher un dialogue lors d’erreurs non capturées
Par défaut, React affichera dans la console toute erreur non capturée. Pour implémenter votre propre signalement, vous pouvez fournir l’option onUncaughtError
:
import { createRoot } from 'react-dom/client';
const root = createRoot(
document.getElementById('root'),
{
onUncaughtError: (error, errorInfo) => {
console.error(
'Erreur non capturée',
error,
errorInfo.componentStack
);
}
}
);
root.render(<App />);
L’option onUncaughtError est une fonction avec deux arguments :
- L’error qui a été levée.
- Un objet errorInfo qui contient la componentStack de l’erreur.
Vous pouvez utiliser l’option onUncaughtError
pour afficher des dialogues d’erreur :
import { createRoot } from "react-dom/client"; import App from "./App.js"; import {reportUncaughtError} from "./reportError"; import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container, { onUncaughtError: (error, errorInfo) => { if (error.message !== 'Known error') { reportUncaughtError({ error, componentStack: errorInfo.componentStack }); } } }); root.render(<App />);
Afficher les erreurs de Périmètres d’Erreurs
Par défaut, React affichera dans la console (au moyen de console.error
) toute erreur capturée par un Périmètre d’Erreurs. Pour remplacer ce comportement, vous pouvez fournir l’option onCaughtError
afin de traiter vous-mêmes les erreurs capturées par un Périmètre d’Erreurs :
import { createRoot } from 'react-dom/client';
const root = createRoot(
document.getElementById('root'),
{
onCaughtError: (error, errorInfo) => {
console.error(
'Erreur capturée',
error,
errorInfo.componentStack
);
}
}
);
root.render(<App />);
L’option onCaughtError est une fonction avec deux arguments :
- L’error qui a été capturée par le Périmètre.
- Un objet errorInfo qui contient la componentStack de l’erreur.
Vous pouvez utiliser l’option onCaughtError
pour afficher des dialogues d’erreur ou retirer les erreurs connues de la journalisation :
import { createRoot } from "react-dom/client"; import App from "./App.js"; import {reportCaughtError} from "./reportError"; import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container, { onCaughtError: (error, errorInfo) => { if (error.message !== 'Known error') { reportCaughtError({ error, componentStack: errorInfo.componentStack, }); } } }); root.render(<App />);
Afficher un dialogue lors d’erreurs récupérables
React est susceptible de refaire le rendu d’un composant afin de tenter de retomber sur ses pieds lorsqu’un rendu lève une erreur. S’il réussit, React affichera en console une erreur récupérable, pour notifier le développeur. Pour remplacer ce comportement, vous pouvez fournir l’option onRecoverableError
:
import { createRoot } from 'react-dom/client';
const root = createRoot(
document.getElementById('root'),
{
onRecoverableError: (error, errorInfo) => {
console.error(
'Erreur récupérable',
error,
error.cause,
errorInfo.componentStack,
);
}
}
);
root.render(<App />);
L’option onRecoverableError est une fonction avec deux arguments :
- L’error qui a été capturée par le Périmètre.
- Un objet errorInfo qui contient la componentStack de l’erreur.
Vous pouvez utiliser l’option onRecoverableError
pour afficher des dialogues d’erreur ou retirer les erreurs connues de la journalisation :
import { createRoot } from "react-dom/client"; import App from "./App.js"; import {reportRecoverableError} from "./reportError"; import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container, { onRecoverableError: (error, errorInfo) => { reportRecoverableError({ error, cause: error.cause, componentStack: errorInfo.componentStack, }); } }); root.render(<App />);
Dépannage
J’ai créé une racine mais rien ne s’affiche
Assurez-vous de ne pas oublier d’afficher effectivement votre appli (avec render
) au sein de la racine :
import { createRoot } from 'react-dom/client';
import App from './App.js';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
Tant que vous ne le faites pas, rien ne sera affiché.
J’ai une erreur : “You passed a second argument to root.render”
Une erreur courante consiste à passer les options de createRoot
à root.render(...)
:
(« Avertissement : vous avez passé un second argument à root.render(…) alors qu’elle n’accepte qu’un argument. », NdT)
Pour corriger ça, passez ces options à createRoot(...)
, pas à root.render(...)
:
// 🚩 Incorrect : root.render ne prend qu’un argument.
root.render(App, {onUncaughtError});
// ✅ Correct : passez les options à createRoot.
const root = createRoot(container, {onUncaughtError});
root.render(<App />);
J’ai une erreur : “Target container is not a DOM element”
(« Le conteneur cible n’est pas un élément DOM », NdT)
Cette erreur signifique que ce que vous avez passé à createRoot
n’est pas un élément DOM.
Si vous ne comprenez pas bien ce qui se passe, essayer d’afficher des informations dans la console :
const domNode = document.getElementById('root');
console.log(domNode); // ???
const root = createRoot(domNode);
root.render(<App />);
Si par exemple domNode
est null
, ça signifie que getElementById
a renvoyé null
. Ça arrive lorsqu’aucun nœud du document n’a l’ID spécifié au moment de l’appel. Il peut y avoir plusieurs raisons à ça :
- L’ID que vous utilisez n’est pas tout à fait celui utilisé dans le HTML. Vérifiez les fautes de frappe !
- La balise
<script>
de votre bundle, si elle est synchrone (cas par défaut), ne peut pas « voir » les nœuds DOM qui apparaissent après elle dans le HTML.
Il est aussi fréquent d’obtenir cette erreur en écrivant par mégarde createRoot(<App />)
plutôt que createRoot(domNode)
.
J’ai une erreur : “Functions are not valid as a React child.”
(« Les fonctions ne constituent pas des enfants React valides », NdT)
Cette erreur signifie que ce que vous avez passé à root.render
n’est pas un composant React.
Ça peut arriver si vous appelez root.render
en lui passant Component
plutôt que <Component />
:
// 🚩 Erroné : App est une function, pas un composant.
root.render(App);
// ✅ Correct : <App /> est un composant.
root.render(<App />);
Ou si vous passez une fonction à root.render
, plutôt que le résultat de l’appel à cette fonction :
// 🚩 Erroné : createApp est une fonction, pas un composant.
root.render(createApp);
// ✅ Correct : appeler createApp renvoie un composant.
root.render(createApp());
Mon HTML produit côté serveur est recréé de zéro
Si votre appli utilise le rendu côté serveur et inclut le HTML initial généré par React, vous remarquerez peut-être qu’en créant une racine pour appeler root.render
, ça supprime tout ce HTML et re-crée les nœuds DOM de zéro. Ça peut être plus lent, mais surtout risque de réinitialiser le focus et la position de défilement tout en perdant les saisies de l’utilisateur.
Les applis qui font un rendu côté serveur doivent utiliser hydrateRoot
plutôt que createRoot
:
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(
document.getElementById('root'),
<App />
);
Remarquez que l’API est différente. En particulier, il n’y aura généralement pas d’appel ultérieur à root.render
.