oleh.meleshko
oleh.meleshko

Reputation: 4795

ReactJS server-side rendering issue

Please help me to understand my issue.

I have the following on the server-side (Node.js):

var React = require('react');
var ReactDOMServer = require('react-dom/server');

var TestComponent = React.createClass({
  render : function() {
    return <div>test</div>
  }
});

// express router callback..
function(req, res, next) {
  res.send(ReactDOMServer.renderToString(TestComponent));
};

An example of response:

<div data-reactid=".2e2hyaaz0n4" data-react-сhecksum="1124798100">test</div>

And on the client-side:

ReactDOM.render(React.createElement(template), document.getElementById('container'));

I'm having the following error in browser console:

Uncaught Invariant Violation: Invalid tag: <div data-reactid=".2e2hyaaz0n4" data-react-checksum="1124798100">test</div>

Any help will be appreciated!

Upvotes: 0

Views: 1406

Answers (3)

Dinesh t
Dinesh t

Reputation: 21

You are trying to mount the component on the element having id container.

ReactDOM.render(React.createElement(template), document.getElementById('container'));

But you missed to add the element with id container in the component rendered from serverside.
To achieve this use a template like Jade.

div(class="container")

renderedHTMLString

If u want to replace entire body just add this client side.

ReactDOM.render(React.createElement(template), document.getElementsByTagName('body')[0]);

Upvotes: 0

Alexander Ivantsov
Alexander Ivantsov

Reputation: 294

The problem with your code is that you send just a div tag without a real document. This means that on the server you should write something like this:

function(req, res, next) {
  const component = ReactDOMServer.renderToString(TestComponent);

  const layout = `<!DOCTYPE html>
    <html>
      <head lang="en">
        <meta charSet="utf-8"/>
        <title>Isomorphic app</title>
      </head>
      <body>
        <div id="container">${component}</div>
      </body>
    </html>`;

  res.send(layout);
};

Also you can check out this repo with an example of simple isomorphic app.

Upvotes: 0

Michelle Tilley
Michelle Tilley

Reputation: 159105

If template contains the string

'<div data-reactid=".2e2hyaaz0n4" data-react-сhecksum="1124798100">test</div>'

then this is not quite correct. You can never render plain HTML as if it were JSX. Instead you should include the server-rendered HTML as part of the page source when it is rendered, and then initialize the client-side React application using the same props as used on the server.

So, for example, using the EJS template engine:

// In Express

function(req, res, next) {
  var reactHtml = ReactDOMServer.renderToString(<TestComponent />);
  res.render('index.ejs', {reactOutput: reactHtml});
};
<!-- In a template somewhere -->
<div id="container"><%- reactOutput %></div>
// In a client-side JavaScript file

var TestComponent = React.createClass({
  render : function() {
    return <div>test</div>
  }
});

ReactDOM.render(<TestComponent />, document.getElementById('container'));

See How to Implement Node + React Isomorphic JavaScript & Why it Matters for more information.

Upvotes: 1

Related Questions