createRoot
createRoot ti permette di creare una root per visualizzare componenti React all’interno di un nodo DOM del browser.
const root = createRoot(domNode, options?)Reference
createRoot(domNode, options?)
Chiama createRoot per creare una root React che visualizza contenuto all’interno di un elemento DOM del browser.
import { createRoot } from 'react-dom/client';
const domNode = document.getElementById('root');
const root = createRoot(domNode);React creerà una root per il domNode e prenderà in carico la gestione del DOM al suo interno. Dopo aver creato una root, devi chiamare root.render per visualizzare un componente React al suo interno:
root.render(<App />);Un’app interamente costruita con React avrà di solito una sola chiamata a createRoot per il componente root. Una pagina che integra React solo in alcune parti può avere tutte le root separate necessarie.
Parameters
-
domNode: Un elemento DOM. React creerà una root per questo elemento DOM e ti permetterà di chiamare funzioni sulla root, comerenderper visualizzare contenuto React renderizzato. -
optional
options: Un oggetto con opzioni per questa root React.- optional
onCaughtError: Callback chiamata quando React cattura un errore in un contenitore di errori. Viene chiamata con l’errorcatturato dal contenitore di errori e un oggettoerrorInfoche contiene ilcomponentStack. - optional
onUncaughtError: Callback chiamata quando viene lanciato un errore e non viene catturato da un contenitore di errori. Viene chiamata con l’errorlanciato e un oggettoerrorInfoche contiene ilcomponentStack. - optional
onRecoverableError: Callback chiamata quando React recupera automaticamente dagli errori. Viene chiamata con unerrorlanciato da React e un oggettoerrorInfoche contiene ilcomponentStack. Alcuni errori recuperabili possono includere la causa originale dell’errore comeerror.cause. - optional
identifierPrefix: Un prefisso stringa che React usa per gli ID generati dauseId. Utile per evitare conflitti quando usi più root sulla stessa pagina.
- optional
Returns
createRoot restituisce un oggetto con due metodi: render e unmount.
Caveats
- Se la tua app è renderizzata lato server, l’uso di
createRoot()non è supportato. UsahydrateRoot()al suo posto. - Probabilmente avrai una sola chiamata a
createRootnella tua app. Se usi un framework, potrebbe eseguire questa chiamata per te. - Quando vuoi renderizzare un pezzo di JSX in una parte diversa dell’albero DOM che non è un figlio del tuo componente (ad esempio, una modale o un tooltip), usa
createPortalinvece dicreateRoot.
root.render(reactNode)
Chiama root.render per visualizzare un pezzo di JSX (“nodo React”) nel nodo DOM del browser della root React.
root.render(<App />);React visualizzerà <App /> nella root e prenderà in carico la gestione del DOM al suo interno.
Parameters
reactNode: Un nodo React che vuoi visualizzare. Di solito sarà un pezzo di JSX come<App />, ma puoi anche passare un elemento React costruito concreateElement(), una stringa, un numero,nulloundefined.
Returns
root.render restituisce undefined.
Caveats
-
La prima volta che chiami
root.render, React cancellerà tutto il contenuto HTML esistente all’interno della root React prima di renderizzare il componente React al suo interno. -
Se il nodo DOM della tua root contiene HTML generato da React sul server o durante la build, usa
hydrateRoot()al suo posto, che collega i gestori di eventi all’HTML esistente. -
Se chiami
rendersulla stessa root più di una volta, React aggiornerà il DOM secondo necessità per riflettere l’ultimo JSX che hai passato. React deciderà quali parti del DOM possono essere riutilizzate e quali devono essere ricreate “confrontandole” con l’albero renderizzato in precedenza. Chiamarerendersulla stessa root di nuovo è simile a chiamare la funzionesetsul componente root: React evita aggiornamenti DOM non necessari. -
Sebbene la renderizzazione sia sincrona una volta avviata,
root.render(...)non lo è. Ciò significa che il codice doporoot.render()può essere eseguito prima che vengano attivati gli Effetti (useLayoutEffect,useEffect) di quella specifica renderizzazione. Di solito va bene e raramente richiede aggiustamenti. Nei rari casi in cui il timing degli Effetti è importante, puoi avvolgereroot.render(...)influshSyncper assicurarti che la renderizzazione iniziale avvenga completamente in modo sincrono.const root = createRoot(document.getElementById('root'));root.render(<App />);// 🚩 L'HTML non includerà ancora <App /> renderizzato:console.log(document.body.innerHTML);
root.unmount()
Chiama root.unmount per distruggere un albero renderizzato all’interno di una root React.
root.unmount();Un’app interamente costruita con React di solito non avrà chiamate a root.unmount.
È soprattutto utile se il nodo DOM della tua root React (o uno dei suoi antenati) può essere rimosso dal DOM da altro codice. Ad esempio, immagina un pannello a schede jQuery che rimuove le schede inattive dal DOM. Se una scheda viene rimossa, tutto al suo interno (incluse le root React al suo interno) verrebbe rimosso dal DOM. In quel caso, devi dire a React di “smettere” di gestire il contenuto della root rimossa chiamando root.unmount. Altrimenti, i componenti all’interno della root rimossa non saprebbero di dover fare pulizia e liberare risorse globali come le sottoscrizioni.
Chiamare root.unmount smonterà tutti i componenti nella root e “scollegherà” React dal nodo DOM root, inclusa la rimozione di qualsiasi gestore di eventi o state nell’albero.
Parameters
root.unmount non accetta parametri.
Returns
root.unmount restituisce undefined.
Caveats
-
Chiamare
root.unmountsmonterà tutti i componenti nell’albero e “scollegherà” React dal nodo DOM root. -
Una volta chiamato
root.unmountnon puoi chiamare di nuovoroot.rendersulla stessa root. Tentare di chiamareroot.rendersu una root smontata lancerà un errore “Cannot update an unmounted root”. Tuttavia, puoi creare una nuova root per lo stesso nodo DOM dopo che la root precedente per quel nodo è stata smontata.
Usage
Renderizzare un’app interamente costruita con React
Se la tua app è interamente costruita con React, crea una singola root per l’intera app.
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);Di solito, devi eseguire questo codice solo una volta all’avvio. Farà quanto segue:
- Troverà il nodo DOM del browser definito nel tuo HTML.
- Visualizzerà il componente React della tua app al suo interno.
import { createRoot } from 'react-dom/client'; import App from './App.js'; import './styles.css'; const root = createRoot(document.getElementById('root')); root.render(<App />);
Se la tua app è interamente costruita con React, non dovresti aver bisogno di creare altre root o di chiamare di nuovo root.render.
Da questo punto in poi, React gestirà il DOM dell’intera app. Per aggiungere altri componenti, annidali all’interno del componente App. Quando devi aggiornare l’UI, ciascuno dei tuoi componenti può farlo usando lo state. Quando devi visualizzare contenuto extra come una modale o un tooltip fuori dal nodo DOM, renderizzalo con un portal.
Renderizzare una pagina parzialmente costruita con React
Se la tua pagina non è interamente costruita con React, puoi chiamare createRoot più volte per creare una root per ogni pezzo di UI di primo livello gestito da React. Puoi visualizzare contenuto diverso in ciascuna root chiamando root.render.
Qui, due componenti React diversi vengono renderizzati in due nodi DOM definiti nel file 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 />);
Potresti anche creare un nuovo nodo DOM con document.createElement() e aggiungerlo manualmente al documento.
const domNode = document.createElement('div');
const root = createRoot(domNode);
root.render(<Comment />);
document.body.appendChild(domNode); // Puoi aggiungerlo ovunque nel documentoPer rimuovere l’albero React dal nodo DOM e pulire tutte le risorse usate da esso, chiama root.unmount.
root.unmount();Questo è soprattutto utile se i tuoi componenti React sono all’interno di un’app scritta in un framework diverso.
Aggiornare un componente root
Puoi chiamare render più di una volta sulla stessa root. Finché la struttura dell’albero dei componenti corrisponde a quanto renderizzato in precedenza, React preserverà lo state. Nota come puoi digitare nell’input, il che significa che gli aggiornamenti dalle ripetute chiamate a render ogni secondo in questo esempio non sono distruttivi:
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);
È poco comune chiamare render più volte. Di solito, i tuoi componenti aggiorneranno lo state al suo posto.
Registrazione degli errori in produzione
Per impostazione predefinita, React registrerà tutti gli errori nella console. Per implementare la tua segnalazione errori, puoi fornire le opzioni root opzionali per i gestori di errori onUncaughtError, onCaughtError e onRecoverableError:
import { createRoot } from "react-dom/client";
import { reportCaughtError } from "./reportError";
const container = document.getElementById("root");
const root = createRoot(container, {
onCaughtError: (error, errorInfo) => {
if (error.message !== "Known error") {
reportCaughtError({
error,
componentStack: errorInfo.componentStack,
});
}
},
});L’opzione onCaughtError è una funzione chiamata con due argomenti:
- L’error che è stato lanciato.
- Un oggetto errorInfo che contiene il componentStack dell’errore.
Insieme a onUncaughtError e onRecoverableError, puoi implementare il tuo sistema di segnalazione errori:
import { createRoot } from "react-dom/client"; import App from "./App.js"; import { onCaughtErrorProd, onRecoverableErrorProd, onUncaughtErrorProd, } from "./reportError"; const container = document.getElementById("root"); const root = createRoot(container, { // Tieni presente di rimuovere queste opzioni in development per sfruttare // i gestori predefiniti di React o implementare il tuo overlay per development. // I gestori sono specificati incondizionatamente qui solo a scopo dimostrativo. onCaughtError: onCaughtErrorProd, onRecoverableError: onRecoverableErrorProd, onUncaughtError: onUncaughtErrorProd, }); root.render(<App />);
Troubleshooting
Ho creato una root, ma non viene visualizzato nulla
Assicurati di non aver dimenticato di renderizzare effettivamente la tua app nella root:
import { createRoot } from 'react-dom/client';
import App from './App.js';
const root = createRoot(document.getElementById('root'));
root.render(<App />);Finché non lo fai, non viene visualizzato nulla.
Ricevo un errore: “You passed a second argument to root.render”
Un errore comune è passare le opzioni per createRoot a root.render(...):
Per risolvere, passa le opzioni root a createRoot(...), non a root.render(...):
// 🚩 Sbagliato: root.render accetta un solo argomento.
root.render(App, {onUncaughtError});
// ✅ Corretto: passa le opzioni a createRoot.
const root = createRoot(container, {onUncaughtError});
root.render(<App />);Ricevo un errore: “Target container is not a DOM element”
Questo errore significa che ciò che passi a createRoot non è un nodo DOM.
Se non sei sicuro di cosa stia succedendo, prova a registrarlo:
const domNode = document.getElementById('root');
console.log(domNode); // ???
const root = createRoot(domNode);
root.render(<App />);Ad esempio, se domNode è null, significa che getElementById ha restituito null. Succederà se non c’è nessun nodo nel documento con l’ID dato al momento della chiamata. Potrebbero esserci alcune ragioni:
- L’ID che stai cercando potrebbe differire dall’ID usato nel file HTML. Controlla gli errori di battitura!
- Il tag
<script>del tuo bundle non può “vedere” nessun nodo DOM che appare dopo di esso nell’HTML.
Un altro modo comune per ottenere questo errore è scrivere createRoot(<App />) invece di createRoot(domNode).
Ricevo un errore: “Functions are not valid as a React child.”
Questo errore significa che ciò che passi a root.render non è un componente React.
Può succedere se chiami root.render con Component invece di <Component />:
// 🚩 Sbagliato: App è una funzione, non un componente.
root.render(App);
// ✅ Corretto: <App /> è un componente.
root.render(<App />);Oppure se passi una funzione a root.render, invece del risultato della sua chiamata:
// 🚩 Sbagliato: createApp è una funzione, non un componente.
root.render(createApp);
// ✅ Corretto: chiama createApp per restituire un componente.
root.render(createApp());Il mio HTML renderizzato lato server viene ricreato da zero
Se la tua app è renderizzata lato server e include l’HTML iniziale generato da React, potresti notare che creare una root e chiamare root.render cancella tutto quell’HTML e ricrea tutti i nodi DOM da zero. Questo può essere più lento, resetta focus e posizioni di scroll e può perdere altri input dell’utente.
Le app renderizzate lato server devono usare hydrateRoot invece di createRoot:
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(
document.getElementById('root'),
<App />
);Nota che la sua API è diversa. In particolare, di solito non ci sarà un’ulteriore chiamata a root.render.