hydrate
's usage is not limited to renderToNodeStream
- you can (actually should) also use it with the classical renderToString
. renderToNodeStream
is essentially the same as renderToString
with exception that it produces an http stream instead of a string. This means that you can send the rendered html to the client byte by byte during rendering, contrary to the standard renderToString
, when you have to wait for the whole html string to be rendered first, and only after can you send it to the client.
ReactDOM.hydrate
is a replacement for standard ReactDOM.render
. The basic (and only?) difference is that, contrary to ReactDOM.render
, it doesn't throw away all the DOM if React's checksum on the client doesn't match the one calculated on the server. It tries to attach React client app to the server-rendered DOM even if there are some subtle differences, by patching just the differing parts.
Due to the streaming nature of renderToNodeStream
, Helmet's server-side usage is practically impossible in the current state of the library - the head
part of the DOM is sent to the server by the time React get's to compute the DOM including Helmet's components. The stream can't just revert and append Helmet's changes to head
.
So to sum, answering your question - renderToNodeStream
solves the problem of synchronous rendering to string by sending stream, but it introduces new problem of not being able to patch the pushed content if some further part of the React App requires it. It doesn't add anything in terms of state changing and rerendering on the server side. On the other hand, hydrate
doesn't introduce anything new in this topic - it's just a tuned up, more forgiving version of the old render
.
The official docs explain a lot! https://reactjs.org/docs/react-dom.html