简体   繁体   中英

Is window.__INITIAL_STATE__ still the preferred way to pass initial state to the client in React Universal apps?

I'm currently reading a book about React and Universal apps in which the author claims that the following is best practice to pass initial state from server to client:

server.js

import React from 'react';
import {renderToStaticMarkup} from 'react-dom/server';
import Myapp from '../MyApp';
import api from '../services';

function renderPage(html, initialData) {
    return `
        <html>
            <body>
                ${html}
            </body>
            <script>
                window.__INITIAL_STATE__ = ${JSON.stringify(initialData)};
            </script>
            <script src="bundle.js"></script>
        </html>
    `;
}

export default function(request, reply) {
    const initialData = api.getData();
    const html = renderToStaticMarkup(<MyApp />);
    reply(renderPage(html, initialData);
}

And then, in the client you would read out the data like this:

bundle.js

const initialData = window.__INITIAL_STATE__ || {};
const mountNode = document.getElementById('root');
ReactDOM.render(<MyApp />, mountNode);

From what I understand is that the initial state first gets converted to a string and then attached as a global object literal to the window object.

This solution looks very rough to me. The book was released in mid 2016. Is usage of window.__INITIAL_STATE__ still the way how to do this or are there better solutions?

For example, I could imagine that it would be possible to offer the initial state in a separate micro service call which then could also be cached better than if the data is embedded directly into the document because then the initial state data has to be transferred every time the page refreshes, even if the data hasn't changed.

Simple answer: Yes.

But I'm not sure why no one has pointed out that you have a very common XSS vulnerability using JSON.stringify(initialData) what you want to do instead is to:

import serialize from 'serialize-javascript';

 window.__INITIAL_STATE__ = ${serialize(initialData)};

HTTP works by caching responses, in your case, if the initial state will always be the same, you can also cache this in server side and display it in the page, it will work faster, because react will have access immediately to this value so it will not have to wait. Also you can also force the browser to cache the page, so the response for the page will be the same with the initial state not changing.

With the extra call request, you rely on the browser to cache that call, but you'll have to build an extra step, make react re-render when the information arrives or block react to render until the information is ready.

So I'll go with number 1, gives you more flexibility and some other nice to have, like server rendering, which can be easily achieved after having the state loaded in the server.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM