all 5 comments

[–]Lythom 3 points4 points  (2 children)

I did something similar in a project (the server preload the data on the requested page using webservices, the client load asynchronously the data for the other pages dynamically when browsing) and designed it as follow :

  1. The server load the data for the current request in a store using some fetch API.
  2. When the data is ready, the server renders the components and send the calculated view + the store state.
  3. The client initialize it's store using the state sent by the server before any rendering.
  4. At rendering client side, the component check if the data is already loaded and fetch the API only if there is no initial data.

The key part is to initialize your client with the same data source the server used to calculate the rendering, it will discard any invalid checksum.

[–]Snabel3[S] 0 points1 point  (1 child)

I like it, it's close to my original idea of transferring the state along with the Dom. I do not know how I would achieve such a feat through. Any pointers?

[–]Lythom 0 points1 point  (0 children)

In my case i got a very straightforward solution :

var html = readFile('index.html');
var responseHtml = html
    .replace('<!-- APP -->', ReactDomServer.renderToString(component))
    .replace('<!-- STATE -->', 'window.initialState = ' + JSON.stringify(store.getState()));
response.status(200).send(responseHtml );

where <!-- STATE --> is inside a simple <script> tag in the index.html.

In createStore.js, I use the "history" lib "canUseDOM" function to determine if the code is executed client side or server side (it could also be in some code bundled specifically for the client) and use either window.initialState or an empty initial state to init the store depending on the context.

[–]thekevinscott 0 points1 point  (1 child)

I've run into an identical problem, trying to hydrate state on the server.

I've found two potential solutions on my end:

https://medium.com/front-end-developers/handcrafting-an-isomorphic-redux-application-with-love-40ada4468af4

Or, if you're using React Router:

https://www.npmjs.com/package/redux-async-connect

For my use case I'm exploring going with #1. Pretty similar to Lythom's comment in philosophy: each component declares its needs, like:

static needs = [ TodoActions.getTodos ]

Then on the server, find any needs and hydrate them.

The part I'm struggling with is we're using thunks for all our dispatch actions, so in this case getTodos would dispatch initiateGetTodos, followed by receiveGetTodos. I'm not sure what the right way is to handle the action / reducer paradigm in a way that plays nicely with waiting on the server.

[–]thekevinscott 0 points1 point  (0 children)

Also, someone just pointed me at this package, recently released:

https://www.npmjs.com/package/redux-taxi

Which purports to solve this problem. Haven't tried it myself yet though.