Ich habe die Dokumentation gelesen, aber den Unterschied zwischen hydrate()
und render()
in React 16 nicht wirklich verstanden .
Ich weiß, hydrate()
wird verwendet, um SSR und clientseitiges Rendering zu kombinieren.
Kann jemand erklären, was feuchtigkeitsspendend ist und was dann der Unterschied in ReactDOM ist?
javascript
reactjs
react-dom
react-fiber
Shabenda
quelle
quelle
Antworten:
Aus den ReactDOMServer- Dokumenten (Schwerpunkt Mine):
Der fett gedruckte Text ist der Hauptunterschied.
render
kann Ihren Knoten ändern, wenn zwischen dem anfänglichen DOM und dem aktuellen DOM ein Unterschied besteht.hydrate
hängt nur Ereignishandler an.Aus dem Github-Problem, das
hydrate
als separate API eingeführt wurde :<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>
Nur zu Ihrer Information, der Grund, warum sie die Attribute nicht gepatcht haben, ist
quelle
class="spinner"
bleibt das Attribut so, wie es im<div>
Element ist.Hydrat wird grundsätzlich bei SSR (Server Side Rendering) verwendet. SSR gibt Ihnen das Skelett- oder HTML-Markup, das von einem Server gesendet wird, damit Ihre Seite beim Laden zum ersten Mal nicht leer ist und Suchmaschinen-Bots sie für SEO indizieren können (ein Anwendungsfall von SSR). Hydrat fügt also das JS Ihrer Seite oder einem Knoten hinzu, auf den SSR angewendet wird. Damit Ihre Seite auf die vom Benutzer durchgeführten Ereignisse reagiert.
Render wird zum Rendern der Komponente im clientseitigen Browser verwendet. Wenn Sie versuchen, das Hydrat durch Render zu ersetzen, wird eine Warnung angezeigt, dass das Rendern veraltet ist und bei SSR nicht verwendet werden kann. es wurde entfernt, weil es im Vergleich zu Hydrat langsam war.
quelle
Zusätzlich zu oben ...
ReactDOM.hydrate()
ist dasselbe wierender()
, wird jedoch verwendet, um einen Container zu hydratisieren (Ereignis-Listener anzuhängen), dessen HTML-Inhalt von ReactDOMServer gerendert wurde. React versucht, Ereignis-Listener an das vorhandene Markup anzuhängen .Die Verwendung von ReactDOM.render () zur Hydratisierung eines vom Server gerenderten Containers ist aufgrund der Langsamkeit veraltet und wird in React 17 entfernt. Verwenden Sie
hydrate()
stattdessen.quelle
Ich habe nichts Spezielles zu dem hinzuzufügen, was oben über die Verwendung von gesagt wurde
hydrate
, aber beim Versuch, etwas darüber zu lernen, habe ich ein kleines Beispiel zusammengestellt. Hier ist die Arbeit für alle, die es hilfreich finden.Tor
Servieren Sie zwei Seiten, eine, die verwendet,
ReactDOM.hydrate
und eine, die verwendetReactDOM.render
. Sie hängen von einigen in JSX geschriebenen Reaktionskomponenten ab, die durch<script>
Tags geladen werden und eine künstliche Verzögerung (vom Server) aufweisen, um den Unterschied zwischenhydrate
und zu veranschaulichenrender
.Grundstruktur
Ergebnisse
Nachdem ich die Seiten generiert und den Server ausgeführt habe, gehe ich zu
127.0.0.1
und werde mit dem Header- Hydrat , einer Schaltfläche und zwei Links angezeigt. Ich kann auf die Schaltfläche klicken, aber es passiert nichts. Nach einigen Augenblicken ist das Laden des Dokuments abgeschlossen und die Schaltfläche beginnt, meine Klicks zu zählen. Dann klicke ich auf den Link "Rendern". Jetzt hat die Seite, die mir präsentiert wird, den Header- Render und zwei Links, aber keine Schaltfläche. Nach wenigen Augenblicken erscheint die Schaltfläche und reagiert sofort.Erläuterung
Auf der Seite "Hydrat" wird das gesamte Markup sofort gerendert, da alle erforderlichen HTML-Dateien mit der Seite bereitgestellt werden. Die Schaltfläche reagiert nicht, da noch keine Rückrufe verbunden sind. Sobald der
components.js
Ladevorgang abgeschlossen ist, wird dasload
Ereignis ausgelöstwindow
und die Rückrufe werden mit verbundenhydrate
.Auf der Seite "Rendern" wird das Schaltflächen-Markup nicht mit der Seite bereitgestellt, sondern nur von eingefügt
ReactDOM.render
, sodass es nicht sofort sichtbar ist. Beachten Sie, wie sich das Erscheinungsbild der Seite durch das endgültige Laden des Skripts grundlegend ändert.Quelle
Hier ist die benutzerdefinierte Reaktionskomponente, die ich verwende. Es wird vom Server im Knoten verwendet, um auf statisch gerenderte Komponenten zu reagieren, und es wird auch dynamisch vom Server zur Verwendung in Seiten geladen (dies ist der Zweck der Suche nach
exports
undReact
Objekten am Anfang der Datei).// 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;
Dies ist das Skript, mit dem alle für den Server erforderlichen Seiten generiert werden. Zuerst wird babel verwendet, um components.jsx in Javascript zu transpilieren, dann werden diese Komponenten zusammen mit React und ReactDOMServer verwendet, um die eigentlichen Seiten zu erstellen. Diese Seiten werden mit der Funktion erstellt,
getPage
die aus der alspageTemplate.js
nächstes gezeigten Datei exportiert wird .// 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);
Diese Datei exportiert nur die
getPage
zuvor erwähnte Funktion.// 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> `; }
Endlich der eigentliche Server
// 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');
quelle
Der gesamte Prozess des Zurücksetzens von Funktionen in den HTML-Code, der bereits in serverseitigem React gerendert wurde, wird als Hydratation bezeichnet.
Der Vorgang des erneuten Renderns über den einmal gerenderten HTML-Code wird daher als Hydratation bezeichnet.
Wenn wir also versuchen, unsere Anwendung durch Aufrufen zu hydratisieren
ReactDOM.render()
, soll dies durch Aufrufen geschehenReactDOM.hydrate()
.quelle
Beim Rendern wird alles im angegebenen Element (in den meisten Fällen als "root" bezeichnet) gelöscht und neu erstellt, während beim Hydrat alles, was sich bereits im angegebenen Element befindet, beibehalten und daraus erstellt wird, wodurch das Laden der ersten Seite beschleunigt wird.
quelle