Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React server-side and client side rendering not seamless

First the page was rendered by the server, then on client/ browser side, the Javascript script re-render the whole page!
I don't think this is how it's supposed to be since it's very bad user experience.

One thing I noticed is that the data-reactid attribute of my root element as rendered by server is some hash like .2t5ll4229s and all the children has that as prefix e.g. .2t5ll4229s.0 (the first child). Whereas, on the browser side, the data-reactid is .0 for the root element and .0.0 for the first child.
If data-reactid is really the culprit here, is there a way to set it a value of choice like eric123 for both client side and server side.

If data-reactid is not the culprit here, how do I go about making server and client side rendering of React seamless i.e. only certain elements should be re-rendered by the client side, not everything!?

My index-server-local.html template:

...
<body>
    <div id="content" class="container-fluid wrapper no-padding-left no-padding-right">
        {{{reactHtml}}}
    </div>
    <script src="bundle.js"></script>
</body>
...

My server.js:

server.get('*', function (req, res) {
        console.log('request url', req.url);
        log.debug('routes are', JSON.stringify(routes));
        res.header("Access-Control-Allow-Origin", "*");
        match({routes, location: req.url}, (error, redirectLocation, renderProps) => {
    if (renderProps) {
        let htmlStr = React.renderToString(<RoutingContext {...renderProps} />);
        res.render('index-server-local', { reactHtml: htmlStr });    
    }
}

My browser.js:

React.render(<Router history={history} routes={routeConfig} />, document.getElementById('content'));

I'm using react-router 1.0.0 and React 0.13.3.

like image 264
ericn Avatar asked Apr 26 '16 05:04

ericn


1 Answers

We need serialize data(or state) in server side, and send it to client side to deserialize, otherwise, the data in client side is different with the moment server render it. it will reload for sure. One exception: pure static page, in this case React recommend us use renderToStaticMarkup

Similar to renderToString, except this doesn't create extra DOM attributes such as data-react-id, that React uses internally. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save lots of bytes.

So, how we serialize - deserialize? Here is a simple version: in your index-server-local.html template:

   <script src="bundle.js"></script>

to:

   <script dangerouslySetInnerHTML={{{{__html: 'window.__data=' + JSON.stringify({key: 'value'})}}}} />
   <script src="bundle.js"></script>

And in client side, we can use __datadata now. how to map the data to your component it's based on your choice.

I recommend Reudx for this:

   createStore(browserHistory, initialState)

And then

   <Provider store={store}>
     { component }
   </Provider>
like image 69
David Guan Avatar answered Sep 27 '22 22:09

David Guan