2

I'm using https://github.com/andreypopp/react-quickstart to render pages serverside, before letting them update dynamically on the client.

Some pages require data from the server. When running on the client, they get this via superagent.

During the initial (server-side) render, I would like getInitialState for the page to get it's data directly.

Is this possible?

2 Answers 2

1

There are a few ways you could go about this.

The template you're using, react-quickstart, uses audreypopp's react-async add-on to handle rendering components with async state. There's a section in its README that goes over this exact scenario: https://github.com/andreypopp/react-async#rendering-async-components-on-server-with-fetched-async-state.

Basically, you can add a third argument to the callback function of ReactAsync.renderComponentToStringWithAsyncState, which points to a snapshot of your current server state. The README provides the following example:

ReactAsync.renderComponentToStringWithAsyncState(
  Component(),
  function(err, markup, data) {
    res.send(ReactAsync.injectIntoMarkup(markup, data, ['./client.js']))
})

injectIntoMarkup injects the pre-fetched state data as a JSON blob which can be referenced elsewhere in your code as window.__reactAsyncStatePacket.

The other way to do this does not use react-async. Instead, you can call React.renderComponentToString, passing your pre-fetched server data as props.

var markup = React.renderComponentToString(
    Item({ data: SERVER_DATA })
);

Note: You'll have to add some conditional logic to your component code to differentiate between receiving your state directly as props or via ajax/superagent, but it should be straightforward.

Now, for For the sake of this example, let say you're using Handlebars/Express, you can inject your component string into a template:

res.render('template', {
    markup: markup
});

And your template:

<div id="container">{{{ markup }}}</div>

Finally, to get your component working nicely on the client, you can call React.renderComponent as you normally would on the client. React knows not to replace components that were just rendered from the server, but will re-render them when necessary in the future.

Hope this helps, and happy to answer any questions!

Sign up to request clarification or add additional context in comments.

2 Comments

@chrisdew was that helpful? Let me know if you have any lingering questions.
Thanks for your answer, I'll accept it once I get some time to try it.
0

react-quickstart was doing what I needed already.

I had an issue in that I didn't realise that getInitialStateAsync is only called on classes which use the mixin ReactAsync.Mixin.

E.g.

var UserPage = React.createClass({
  mixins: [ReactAsync.Mixin],

  statics: {
    getUserInfo: function(username, cb) {
      superagent.get(
        'http://localhost:3000/api/users/' + username,
        function(err, res) {
          cb(err, res ? res.body : null);
        });
    }
  },

  getInitialStateAsync: function(cb) {
    this.type.getUserInfo(this.props.username, function(arg0, arg1) {
      cb(arg0, arg1)
    });
  },

  ...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.