Leí la documentación, pero realmente no entendí la diferencia entre hydrate()
y render()
en React 16.
Sé que hydrate()
se usa para combinar SSR y renderizado del lado del cliente.
¿Alguien puede explicar qué es hidratante y luego cuál es la diferencia en ReactDOM?
javascript
reactjs
react-dom
react-fiber
shabenda
fuente
fuente
Respuestas:
De los documentos de ReactDOMServer (el énfasis es mío):
El texto en negrita es la principal diferencia.
render
puede cambiar su nodo si hay una diferencia entre el DOM inicial y el DOM actual.hydrate
solo adjuntará controladores de eventos.Del problema de Github que se presentó
hydrate
como una API separada :<div id="container"> <div class="spinner">Loading...</div> </div>
ReactDOM.render( <div class="myapp"> <span>App</span> </div>, document.getElementById('container') )
<div id="container"> <div class="spinner"> <span>App</span> </div> </div>
Para su información, la razón por la que no parchearon los atributos es
fuente
class="spinner"
permanece como está en el<div>
elemento.Hydrate se usa básicamente en el caso de SSR (renderización del lado del servidor). SSR le brinda el esqueleto o el marcado HTML que se envía desde un servidor para que, por primera vez, cuando se cargue su página, no esté en blanco y los robots de los motores de búsqueda puedan indexarlo para SEO (un caso de uso de SSR). Entonces hydrate agrega el JS a su página o un nodo al que se aplica SSR. Para que tu página responda a los eventos realizados por el usuario.
Render se utiliza para renderizar el componente en el navegador del lado del cliente. Además, si intenta reemplazar el hidrato con render, recibirá una advertencia de que el renderizado está obsoleto y no se puede usar en caso de SSR. se eliminó debido a que es lento en comparación con la hidratación.
fuente
No tengo nada específico que agregar a lo que se dijo anteriormente sobre el uso de
hydrate
, pero al tratar de aprender al respecto, reuní un pequeño ejemplo, así que aquí está el trabajo para quien lo encuentre útil.Objetivo
Sirva dos páginas, una que usa
ReactDOM.hydrate
y otra que usaReactDOM.render
. Dependerán de algunos componentes de reacción escritos en JSX, que se cargan mediante<script>
etiquetas, dado un retraso artificial (por parte del servidor) para ilustrar la diferencia entrehydrate
yrender
.Estructura basica
Resultados
Después de generar las páginas y ejecutar el servidor, voy a
127.0.0.1
y se me presenta el encabezado hidratar , un botón y dos enlaces. Puedo hacer clic en el botón, pero no pasa nada. Después de unos momentos, el documento termina de cargarse y el botón comienza a contar mis clics. Luego hago clic en el enlace "render". Ahora, la página que se me presenta tiene la representación del encabezado y dos enlaces, pero ningún botón. Después de unos momentos, aparece el botón y responde de inmediato.Explicación
En la página "hidratar", todo el marcado se procesa inmediatamente, porque todo el html necesario se sirve con la página. El botón no responde porque aún no hay devoluciones de llamada conectadas. Una vez que
components.js
termina de cargarse, elload
evento se dispara desdewindow
y se conectan las devoluciones de llamada conhydrate
.En la página "renderizar", el marcado del botón no se sirve con la página, solo se inyecta por
ReactDOM.render
, por lo que no es visible de inmediato. Observe cómo la apariencia de la página cambia de manera discordante debido a que el script finalmente se carga.Fuente
Aquí está el componente de reacción personalizado que estoy usando. Será utilizado por el servidor en el nodo con reaccionar para renderizar componentes estáticamente, y también se cargará dinámicamente desde el servidor para su uso en las páginas (este es el propósito de comprobar los objetos
exports
yReact
al principio del archivo).// components.jsx var exports = typeof(exports) == 'object' ? exports : {}; var React = typeof(React) == 'object' ? React : require('react'); function MyButton(props) { [click, setClick] = React.useState(0); function handleClick() { setClick(click + 1); } return ( <button onClick={handleClick}>Clicked: {click}</button> ); } exports.MyButton = MyButton;
Este es el script que se utiliza para generar todas las páginas necesarias para el servidor. Primero, se usa babel para transpilar components.jsx en javascript, luego estos componentes se usan, junto con React y ReactDOMServer, para crear las páginas reales. Estas páginas se crean con la función
getPage
que se exporta del archivopageTemplate.js
, que se muestra a continuación.// genScript.js let babel = require('@babel/core'); let fs = require('fs'); let ReactDOMServer = require('react-dom/server'); let React = require('react'); let pageTemplate = require('./pageTemplate.js'); script = babel.transformFileSync( 'components.jsx', {presets : [['@babel/react']]} ); fs.writeFileSync('components.js',script.code); let components = require('./components.js'); hydrateHTML = pageTemplate.getPage( 'MyButton', ReactDOMServer.renderToString(React.createElement(components.MyButton)), 'hydrate' ); renderHTML = pageTemplate.getPage( 'MyButton', '', 'render' ); fs.writeFileSync('hydrate.html',hydrateHTML); fs.writeFileSync('render.html',renderHTML);
Este archivo solo exporta la
getPage
función mencionada anteriormente.// pageTemplate.js exports.getPage = function( reactElementTag, reactElementString, reactDOMMethod ) { return ` <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js" defer></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" defer></script> <script src="./components.js" defer></script> </head> <body> <h1>${ reactDOMMethod }</h1> <div id="react-root">${ reactElementString }</div> <a href="hydrate.html">hydrate</a> <a href="render.html">render</a> </body> <script> window.addEventListener('load', (e) => { ReactDOM.${ reactDOMMethod }( React.createElement(${ reactElementTag }), document.getElementById('react-root') ); }); </script> </html> `; }
Finalmente, el servidor real
// server.js let http = require('http'); let fs = require('fs'); let renderPage = fs.readFileSync('render.html'); let hydratePage = fs.readFileSync('hydrate.html'); let componentsSource = fs.readFileSync('components.js'); http.createServer((req, res) => { if (req.url == '/components.js') { // artificial delay setTimeout(() => { res.setHeader('Content-Type','text/javascript'); res.end(componentsSource); }, 2000); } else if (req.url == '/render.html') { res.end(renderPage); } else { res.end(hydratePage); } }).listen(80,'127.0.0.1');
fuente
Además de lo anterior ...
ReactDOM.hydrate()
es igual querender()
, pero se usa para hidratar (adjuntar oyentes de eventos) un contenedor cuyo contenido HTML fue renderizado por ReactDOMServer. React intentará adjuntar oyentes de eventos al marcado existente .El uso de ReactDOM.render () para hidratar un contenedor renderizado por el servidor está obsoleto debido a la lentitud y se eliminará en React 17, así que utilícelo
hydrate()
en su lugar.fuente
Todo el proceso de volver a poner la funcionalidad en el HTML que ya se renderizó en el lado del servidor React se llama hidratación.
Por lo tanto, el proceso de volver a renderizar sobre el HTML una vez renderizado se conoce como hidratación.
Entonces, si intentamos hidratar nuestra aplicación llamando, se
ReactDOM.render()
supone que debe hacerse llamandoReactDOM.hydrate()
.fuente
render eliminará cualquier cosa en el elemento especificado (llamado 'raíz' en la mayoría de los casos) y lo reconstruirá, mientras que hydrate mantendrá todo lo que ya esté dentro del elemento especificado y construirá a partir de eso, haciendo que la página inicial se cargue más rápido.
fuente