0

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!

3 Answers 3

1

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.

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

14 Comments

Please check that facebook.github.io/react/docs/… Looks like it should be possible..
@OlegMeleshko Can you elaborate? I'm not sure what you mean by your comment.
If you call ReactDOM.render() on a node that already has this server-rendered markup, React will preserve it and only attach event handlers, allowing you to have a very performant first-load experience.
@OlegMeleshko That is correct. To do that, you would use the strategy outlined here — output the server-rendered markup as part of the HTML template, then call render on the node that already contains the markup using the same input JSX. You cannot fetch the HTML from the page and call render on that.
I'm getting my html via ajax, so do you mean I could wrap it up somehow and then render as a React component?
|
0

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.

1 Comment

Nope, it's not what I want.
0

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]);

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.