hydrateRoot
hydrateRoot
te permite mostrar componentes de React dentro de un nodo DOM del navegador cuyo contenido HTML fue generado previamente por react-dom/server
.
const root = hydrateRoot(domNode, reactNode, options?)
- Referencia
- Uso
- Hidratación de HTML renderizado en el servidor
- Hidratar un documento completo
- Suprimir errores inevitables de desajuste de hidratación
- Manejar diferentes contenidos de cliente y servidor
- Actualización de un componente raíz hidratado
- Show a dialog for uncaught errors
- Displaying Error Boundary errors
- Show a dialog for recoverable hydration mismatch errors
- Troubleshooting
Referencia
hydrateRoot(domNode, reactNode, options?)
Llama a hydrateRoot
para «adjuntar» React al HTML existente que ya fue renderizado por React en un entorno del servidor.
import { hydrateRoot } from 'react-dom/client';
const domNode = document.getElementById('root');
const root = hydrateRoot(domNode, reactNode);
React se unirá al HTML que existe dentro de domNode
, y se encargará de gestionar el DOM dentro de él. Una aplicación completamente construida con React normalmente sólo tendrá una llamada a hydrateRoot
con su componente raíz.
Parámetros
-
domNode
: Un elemento del DOM que se ha renderizado como el elemento raíz en el servidor. -
reactNode
: El «nodo de React» utilizado para renderizar el HTML existente. Normalmente será un trozo de JSX como<App />
que se ha renderizado con un método deReactDOM Server
comorenderToPipeableStream(<App />)
. -
opcional
options
: Un objeto que contiene opciones para esta raíz de React.- Canary only optional
onCaughtError
: Callback called when React catches an error in an Error Boundary. Called with theerror
caught by the Error Boundary, and anerrorInfo
object containing thecomponentStack
. - Canary only optional
onUncaughtError
: Callback called when an error is thrown and not caught by an Error Boundary. Called with theerror
that was thrown and anerrorInfo
object containing thecomponentStack
. - optional
onRecoverableError
: Callback called when React automatically recovers from errors. Called with theerror
React throws, and anerrorInfo
object containing thecomponentStack
. Some recoverable errors may include the original error cause aserror.cause
. - opcional
identifierPrefix
: Prefijo que React utiliza para los IDs generados poruseId
. Útil para evitar conflictos cuando se utilizan varias raíces en la misma página. Debe ser el mismo prefijo que se utiliza en el servidor.
- Canary only optional
Devuelve
hydrateRoot
devuelve un objeto con dos métodos: render
y unmount
.
Advertencias
hydrateRoot()
espera que el contenido renderizado sea idéntico al contenido renderizado por el servidor. Deberías tratar los desajustes como errores y solucionarlos.- En el modo de desarrollo, React avisa de los desajustes durante la hidratación. No hay garantías de que las diferencias de atributos sean parcheadas en caso de desajustes. Esto es importante por razones de rendimiento, ya que en la mayoría de las aplicaciones, los desajustes son raros, por lo que validar todo el marcado sería prohibitivamente caro.
- Es probable que sólo tengas una llamada a
hydrateRoot
en tu aplicación. Si utilizas un framework, puede que la haga por ti. - Si tu aplicación está renderizada en el cliente y no tiene HTML renderizado, el uso de
hydrateRoot()
no es válido. UtilizacreateRoot()
en su lugar.
root.render(reactNode)
Llama a root.render
para actualizar un componente de React dentro de una raíz de React hidratada para un elemento DOM del navegador.
root.render(<App />);
React actualizará <App />
en la raíz hidratada (root
).
Parámetros
reactNode
: Un «nodo de React» que quieres actualizar. Normalmente será un trozo de JSX como<App />
, pero también puedes pasar un elemento React construido concreateElement()
., un string, un número,null
, oundefined
.
Devuelve
root.render
devuelve undefined
.
Advertencias
- Si llamas a
root.render
antes de que la raíz haya terminado de hidratarse, React borrará el contenido HTML existente renderizado por el servidor y cambiará toda la raíz a renderizado del cliente.
root.unmount()
Llama a root.unmount
para destruir un árbol renderizado dentro de una raíz de React.
root.unmount();
Una aplicación completamente construida con React normalmente no tendrá ninguna llamada a root.unmount
.
Esto es útil mayormente si el nodo DOM de tu raíz de React (o cualquiera de sus ancestros) puede ser eliminado del DOM por algún otro código. Por ejemplo, imagina un panel de pestañas jQuery que elimina las pestañas inactivas del DOM. Si se elimina una pestaña, todo lo que hay dentro de ella (incluyendo las raíces React que hay dentro) se eliminará también del DOM. En ese caso, tienes que decirle a React que «deje» de gestionar el contenido de la raíz eliminada llamando a root.unmount
. De lo contrario, los componentes dentro de la raíz eliminada no sabrán limpiar y liberar recursos globales como las suscripciones.
Al llamar a root.unmount
se desmontarán todos los componentes de la raíz y se «separará» React del nodo DOM raíz, incluyendo la eliminación de cualquier controlador de evento o estado en el árbol.
Parámetros
root.unmount
no acepta ningún parámetro.
Devuelve
root.unmount
devuelve undefined
.
Advertencias
-
Llamando a
root.unmount
se desmontarán todos los componentes del árbol y se «separará» React del nodo DOM raíz. -
Una vez que se llama a
root.unmount
no se puede volver a llamar aroot.render
en la raíz. El intento de llamar aroot.render
en una raíz desmontada arrojará el error «Cannot update an unmounted root» (No se puede actualizar una raíz desmontada).
Uso
Hidratación de HTML renderizado en el servidor
Si el HTML de tu aplicación fue generado por react-dom/server
, hay que hidratarlo en el cliente.
import { hydrateRoot } from 'react-dom/client';
hydrateRoot(document.getElementById('root'), <App />);
Esto hidratará el HTML del servidor dentro del nodo DOM del navegador con el componente de React para tu aplicación. Por lo general, lo harás una vez al inicio. Si utilizas un framework, puede que tras bambalinas lo haga por ti.
Para hidratar tu aplicación, React «adjuntará» la lógica de tus componentes al HTML inicial generado desde el servidor. La hidratación convierte la instantánea inicial de HTML del servidor en una aplicación totalmente interactiva que se ejecuta en el navegador.
import './styles.css'; import { hydrateRoot } from 'react-dom/client'; import App from './App.js'; hydrateRoot( document.getElementById('root'), <App /> );
No deberías necesitar llamar a hydrateRoot
de nuevo o llamarlo en más sitios. A partir de este punto, React gestionará el DOM de tu aplicación. Si quieres actualizar la interfaz de usuario, tus componentes pueden hacerlo usando el estado.
Hidratar un documento completo
Las aplicaciones construidas completamente con React pueden renderizar un documento completo a partir del componente raíz, incluyendo la etiqueta 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>My app</title>
</head>
<body>
<Router />
</body>
</html>
);
}
Para hidratar el documento completo, pasa la variable global document
como primer argumento a hydrateRoot
:
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(document, <App />);
Suprimir errores inevitables de desajuste de hidratación
Si el atributo o contenido de texto de un único elemento es inevitablemente diferente entre el servidor y el cliente (por ejemplo, una marca de tiempo), puede silenciar la advertencia de desajuste de hidratación.
Para silenciar las advertencias de hidratación en un elemento, agrega suppressHydrationWarning={true}
:
export default function App() { return ( <h1 suppressHydrationWarning={true}> Fecha actual: {new Date().toLocaleDateString()} </h1> ); }
Esto sólo funciona a un nivel de profundidad, y pretende ser una vía de escape. No abuses de su uso. A menos que sea contenido de texto, React aún no intentará parchearlo, por lo que puede permanecer inconsistente hasta futuras actualizaciones.
Manejar diferentes contenidos de cliente y servidor
Si intencionalmente necesitas renderizar algo diferente en el servidor y en el cliente, puedes hacer un renderizado de dos pasadas. Los componentes que renderizan algo diferente en el cliente pueden leer una variable de estado como isClient
, que puedes establecer en true
en un Efecto:
import { useState, useEffect } from "react"; export default function App() { const [isClient, setIsClient] = useState(false); useEffect(() => { setIsClient(true); }, []); return ( <h1> {isClient ? 'Es Cliente' : 'Es Servidor'} </h1> ); }
De esta forma el pase de render inicial renderizará el mismo contenido que el servidor, evitando desajustes, pero un pase adicional sucederá de forma sincrónica justo después de la hidratación.
Actualización de un componente raíz hidratado
Después de que la raíz haya terminado de hidratarse, puedes llamar a root.render
para actualizar el componente raíz de React. Al contrario que con createRoot
, normalmente no es necesario hacerlo porque el contenido inicial ya se ha renderizado como HTML.
Si llamas a root.render
en algún momento después de la hidratación, y la estructura del árbol de componentes coincide con lo que se renderizó previamente, React preservará el estado. Fíjate que puedes escribir en la entrada de texto, lo que significa que las actualizaciones de las llamadas sucesivas a render
cada segundo en este ejemplo no son destructivas:
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);
Es poco común llamar a root.render
en una raíz hidratada. Por lo general, lo que deberías hacer es actualizar el estado dentro de uno de los componentes.
Show a dialog for uncaught errors
By default, React will log all uncaught errors to the console. To implement your own error reporting, you can provide the optional onUncaughtError
root option:
import { hydrateRoot } from 'react-dom/client';
const root = hydrateRoot(
document.getElementById('root'),
<App />,
{
onUncaughtError: (error, errorInfo) => {
console.error(
'Uncaught error',
error,
errorInfo.componentStack
);
}
}
);
root.render(<App />);
The onUncaughtError option is a function called with two arguments:
- The error that was thrown.
- An errorInfo object that contains the componentStack of the error.
You can use the onUncaughtError
root option to display error dialogs:
import { hydrateRoot } from "react-dom/client"; import App from "./App.js"; import {reportUncaughtError} from "./reportError"; import "./styles.css"; import {renderToString} from 'react-dom/server'; const container = document.getElementById("root"); const root = hydrateRoot(container, <App />, { onUncaughtError: (error, errorInfo) => { if (error.message !== 'Known error') { reportUncaughtError({ error, componentStack: errorInfo.componentStack }); } } });
Displaying Error Boundary errors
By default, React will log all errors caught by an Error Boundary to console.error
. To override this behavior, you can provide the optional onCaughtError
root option for errors caught by an Error Boundary:
import { hydrateRoot } from 'react-dom/client';
const root = hydrateRoot(
document.getElementById('root'),
<App />,
{
onCaughtError: (error, errorInfo) => {
console.error(
'Caught error',
error,
errorInfo.componentStack
);
}
}
);
root.render(<App />);
The onCaughtError option is a function called with two arguments:
- The error that was caught by the boundary.
- An errorInfo object that contains the componentStack of the error.
You can use the onCaughtError
root option to display error dialogs or filter known errors from logging:
import { hydrateRoot } from "react-dom/client"; import App from "./App.js"; import {reportCaughtError} from "./reportError"; import "./styles.css"; const container = document.getElementById("root"); const root = hydrateRoot(container, <App />, { onCaughtError: (error, errorInfo) => { if (error.message !== 'Known error') { reportCaughtError({ error, componentStack: errorInfo.componentStack }); } } });
Show a dialog for recoverable hydration mismatch errors
When React encounters a hydration mismatch, it will automatically attempt to recover by rendering on the client. By default, React will log hydration mismatch errors to console.error
. To override this behavior, you can provide the optional onRecoverableError
root option:
import { hydrateRoot } from 'react-dom/client';
const root = hydrateRoot(
document.getElementById('root'),
<App />,
{
onRecoverableError: (error, errorInfo) => {
console.error(
'Caught error',
error,
error.cause,
errorInfo.componentStack
);
}
}
);
The onRecoverableError option is a function called with two arguments:
- The error React throws. Some errors may include the original cause as error.cause.
- An errorInfo object that contains the componentStack of the error.
You can use the onRecoverableError
root option to display error dialogs for hydration mismatches:
import { hydrateRoot } from "react-dom/client"; import App from "./App.js"; import {reportRecoverableError} from "./reportError"; import "./styles.css"; const container = document.getElementById("root"); const root = hydrateRoot(container, <App />, { onRecoverableError: (error, errorInfo) => { reportRecoverableError({ error, cause: error.cause, componentStack: errorInfo.componentStack }); } });
Troubleshooting
I’m getting an error: «You passed a second argument to root.render»
A common mistake is to pass the options for hydrateRoot
to root.render(...)
:
To fix, pass the root options to hydrateRoot(...)
, not root.render(...)
:
// 🚩 Wrong: root.render only takes one argument.
root.render(App, {onUncaughtError});
// ✅ Correct: pass options to createRoot.
const root = hydrateRoot(container, <App />, {onUncaughtError});