createRoot

Nota bene

Questa pagina è stata tradotta automaticamente e supervisionata da un maintainer. Un’ulteriore revisione da parte della community sarebbe comunque utile. Migliora questa traduzione.

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.

Vedi altri esempi sotto.

Parameters

  • domNode: Un elemento DOM. React creerà una root per questo elemento DOM e ti permetterà di chiamare funzioni sulla root, come render per 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’error catturato dal contenitore di errori e un oggetto errorInfo che contiene il componentStack.
    • optional onUncaughtError: Callback chiamata quando viene lanciato un errore e non viene catturato da un contenitore di errori. Viene chiamata con l’error lanciato e un oggetto errorInfo che contiene il componentStack.
    • optional onRecoverableError: Callback chiamata quando React recupera automaticamente dagli errori. Viene chiamata con un error lanciato da React e un oggetto errorInfo che contiene il componentStack. Alcuni errori recuperabili possono includere la causa originale dell’errore come error.cause.
    • optional identifierPrefix: Un prefisso stringa che React usa per gli ID generati da useId. Utile per evitare conflitti quando usi più root sulla stessa pagina.

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. Usa hydrateRoot() al suo posto.
  • Probabilmente avrai una sola chiamata a createRoot nella 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 createPortal invece di createRoot.

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.

Vedi altri esempi sotto.

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 con createElement(), una stringa, un numero, null o undefined.

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 render sulla 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. Chiamare render sulla stessa root di nuovo è simile a chiamare la funzione set sul 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 dopo root.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 avvolgere root.render(...) in flushSync per 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.unmount smonterà tutti i componenti nell’albero e “scollegherà” React dal nodo DOM root.

  • Una volta chiamato root.unmount non puoi chiamare di nuovo root.render sulla stessa root. Tentare di chiamare root.render su 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:

  1. Troverà il nodo DOM del browser definito nel tuo HTML.
  2. 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.

Nota bene

Quando il tuo HTML è vuoto, l’utente vede una pagina bianca finché il codice JavaScript dell’app non viene caricato ed eseguito:

<div id="root"></div>

Questo può sembrare molto lento! Per risolvere, puoi generare l’HTML iniziale dai tuoi componenti sul server o durante la build. Così i visitatori possono leggere testo, vedere immagini e cliccare link prima che venga caricato qualsiasi codice JavaScript. Consigliamo di usare un framework che esegue questa ottimizzazione out of the box. A seconda di quando viene eseguita, si parla di server-side rendering (SSR) o static site generation (SSG).

Insidia

Le app che usano la renderizzazione lato server o la generazione statica devono chiamare hydrateRoot invece di createRoot. React idraterà (riutilizzerà) i nodi DOM dal tuo HTML invece di distruggerli e ricrearli.


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 documento

Per 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:

  1. L’error che è stato lanciato.
  2. 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(...):

Console
Warning: You passed a second argument to root.render(…) but it only accepts one argument.

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:

  1. L’ID che stai cercando potrebbe differire dall’ID usato nel file HTML. Controlla gli errori di battitura!
  2. 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.