简体   繁体   中英

With React / Redux, how do I dynamically pre-load state?

I'm having a hard time pre-loading state with React / Redux.

Before marking this as duplicate, I've already read these:

Here's my scenario:

  • I'm using Node + React + Redux.
  • When I load a page, from the server, I load User object from the database. I need this User object to be in the state without a roundtrip to the server .
  • Because the User object is dynamic, I can't have it in the bundle.
  • I'm not using server-rendering.

My problem:

How do I initially load the User object from the server into my store in the Client?

In this answer , Dan Abramov says:

On the client, you'd read it from a global variable , and create the client store instance with it. In other words you never have to manually create initialState—you're supposed to grab it on the server with store.getState(), pass it to client, and create a store with it.

So, I'm assuming that, by global variable , he means something like this:

// Here, window._initialState.user is being sent to the client in a <script/> tag.
const store = createStore(reducers, { user: window._initialState.user);

The above might work, the problem is that I don't have confidence that this is actually a good practice because I didn't find any example on the internet about it.

So, Is this the right thing to do? Is there a better / more recommended way of doing it?

This is taken directly from the redux recipes page :

To pass along the state, we add a tag that will attach preloadedState to window.__PRELOADED_STATE__ .

function renderFullPage(html, preloadedState) {
return `
    <!doctype html>
    <html>
    <head>
        <title>Redux Universal Example</title>
    </head>
    <body>
        <div id="root">${html}</div>
        <script>
        // WARNING: See the following for security issues around embedding JSON in HTML:
        // http://redux.js.org/docs/recipes/ServerRendering.html#security-considerations
        window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, '\\u003c')}
        </script>
        <script src="/static/bundle.js"></script>
    </body>
    </html>
    `
}

When I load a page, from the server, I load User object from the database. I need this User object to be in the state without a roundtrip to the server.

I would argue that you should make an initial round trip to the server if you're not server rendering. The way I see it is that you have to make at least two calls to the server: one for your cache-able bundle, and one for the data. Even if you're loading a script that will set a global variable with some initial state, you still have to make another call to get the bundle right? I might be misunderstanding but I don't see an advantage in setting the initial state in the way you're describing. If you're not server rendering then maybe a plain-ole restful API and SPA is simpler.

How do I initially load the User object from the server into my store in the Client?

My suggestion is to just make the that first round trip the server and wait for the fetch promise to resolve, then create your store and render the app.

fetch('http://example.com/something').then(data => data.json()).then(initalState => {
    render(
        <Provider store={/*stored created with initalState*/}>
            <App />
        </Provider>,
        document.getElementById('app')
    )
});

Again, I might be misunderstanding your problem/architecture here but this is just my two cents. Good luck!

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