Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Server-side rendering with ReactDOM.hydrate

hydrate has landed to React 16, but its use isn't documented yet.

This article suggests that it is is supposed to be used with renderToNodeStream but doesn't give much details.

What is the expected usage of hydrate?

renderToString is synchronous. It also cannot handle re-rendered components, i.e. when synchronous (i.e. same tick) changes happen in component state during initial rendering and are supposed to trigger additional render calls. The example is Helmet that requires a workaround in order to propagate changes from nested Helmet back to top-level component on server side.

Can hydrate and renderToNodeStream help to avoid renderToString limitations and render asynchronous and/or re-rendered components on server side?

like image 273
Estus Flask Avatar asked Sep 25 '17 11:09

Estus Flask


People also ask

What is hydration server-side rendering?

Hydration is the process of using client-side JavaScript to add application state and interactivity to server-rendered HTML. It's a feature of React, one of the underlying tools that make the Gatsby framework. Gatsby uses hydration to transform the static HTML created at build time into a React application.

What does ReactDOM hydrate do?

React hydration is a technique used that is similar to rendering, but instead of having an empty DOM to render all of our react components into, we have a DOM that has already been built, with all our components rendered as HTML.

Is ReactDOM render still used?

The render() method of the react-dom package is considered legacy starting react-dom version 18. The method is replaced with the createRoot() method that is exported from react-dom/client . The createRoot() method takes the root element as a parameter and creates a React root.

What is difference between ReactDOM and render render?

render renders your components to the DOM while a component's render returns the elements that make up the component.


1 Answers

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

like image 68
jalooc Avatar answered Oct 12 '22 07:10

jalooc