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

hydrateRoot(domNode, 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.

Consulta los ejemplos anteriores.

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 de ReactDOM Server como renderToPipeableStream(<App />).

  • opcional options: Un objeto que contiene opciones para esta ra√≠z de React.

    • opcional onRecoverableError: Callback que se llama cuando React se recupera autom√°ticamente de los errores.
    • opcional identifierPrefix: Prefijo que React utiliza para los IDs generados por useId. √ö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.
    • opcional nonce:

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. Utiliza createRoot() 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).

Consulta m√°s ejemplos debajo.

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 con createElement()., un string, un n√ļmero, null, o undefined.

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 eventos o estado en el √°rbol.

Par√°metros

root.unmount no acepta ning√ļn par√°metro.

Devuelve

render devuelve null.

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 a root.render en la ra√≠z. El intento de llamar a root.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.

Atención

El √°rbol de React que pases a hydrateRoot tiene que producir la misma salida que en el servidor.

Esto es importante para la experiencia del usuario. El usuario pasar√° alg√ļn tiempo mirando el HTML generado por el servidor antes de que se cargue tu c√≥digo JavaScript. El renderizado del servidor crea la ilusi√≥n de que la aplicaci√≥n se carga m√°s r√°pido al mostrar la instant√°nea del HTML de su salida. Mostrar de repente un contenido diferente rompe esa ilusi√≥n. Por ello, la salida de renderizado del servidor debe coincidir con la salida del renderizado inicial en el cliente durante la hidrataci√≥n.

Las causas más comunes que conducen a errores de hidratación incluyen:

  • Espacios en blanco extra (como nuevas l√≠neas) alrededor del HTML generado por React dentro del nodo ra√≠z.
  • Utilizar comprobaciones como typeof window !== 'undefined' en tu l√≥gica de renderizado.
  • Utilizar APIs exclusivas del navegador como window.matchMedia en tu l√≥gica de renderizado.
  • Renderizar datos diferentes en el servidor y en el cliente.

React puede recuperarse de algunos errores de hidratación, pero debes solucionarlos como cualquier otro error. En el mejor de los casos, conducirán a una aplicación más lenta; en el peor, los manejadores de eventos se adjuntarán a los elementos equivocados.


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 />);

Suppressing unavoidable hydration mismatch errors

If a single element’s attribute or text content is unavoidably different between the server and the client (for example, a timestamp), you may silence the hydration mismatch warning.

To silence hydration warnings on an element, add suppressHydrationWarning={true}:

export default function App() {
  return (
    <h1 suppressHydrationWarning={true}>
      Current Date: {new Date().toLocaleDateString()}
    </h1>
  );
}

This only works one level deep, and is intended to be an escape hatch. Don’t overuse it. Unless it’s text content, React still won’t attempt to patch it up, so it may remain inconsistent until future updates.


Handling different client and server content

If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a state variable like isClient, which you can set to true in an Effect:

import { useState, useEffect } from "react";

export default function App() {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  return (
    <h1>
      {isClient ? 'Is Client' : 'Is Server'}
    </h1>
  );
}

This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration.

Atención

This approach makes hydration slower because your components have to render twice. Be mindful of the user experience on slow connections. The JavaScript code may load significantly later than the initial HTML render, so rendering a different UI immediately after hydration may also feel jarring to the user.


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.