aickin / react-dom-stream

A streaming server-side rendering library for React.
2.01k stars 48 forks source link

React attempted to reuse markup in a container but the checksum was invalid. #19

Open samaleksov opened 8 years ago

samaleksov commented 8 years ago

Hi guys, I was making a small POC with the stream SSR, and React seems to be complaining about the checksum while reattaching the DOM.

Just wanted to know if I'm doing something wrong or this is just a version difference between the react-dom-stream fork and react-dom.

This is the warning from React:

app.js:1243 Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
 (client) <div data-reactroot="" data-reactid
 (server) <div data-reactid=".57vkf2fmyo"><h1warning @ app.js:1243ReactMount._mountImageIntoNode @ app.js:12993ReactMount__mountImageIntoNode @ app.js:13855mountComponentIntoNode @ app.js:12649Mixin.perform @ app.js:17286batchedMountComponentIntoNode @ app.js:12663Mixin.perform @ app.js:17286ReactDefaultBatchingStrategy.batchedUpdates @ app.js:10689batchedUpdates @ app.js:15009ReactMount._renderNewRootComponent @ app.js:12816ReactMount__renderNewRootComponent @ app.js:13855ReactMount._renderSubtreeIntoContainer @ app.js:12893ReactMount.render @ app.js:12913React_render @ app.js:138551.react @ app.js:14s @ app.js:1e @ app.js:1(anonymous function) @ app.js:1

This is the code I've used to attach the client in both tests:

ReactDOM.render(<div><h1>{InitData.welcomeText}</h1></div>, document.getElementById("app"));

This is what gets rendered with the original React DOM:

<html>
   <head>
      <title>SSR POC</title>
   </head>
   <body>
      <div id="app">
         <div data-reactroot="" data-reactid="1" data-react-checksum="-503964732">
            <h1 data-reactid="2">Hello World :)</h1>
         </div>
      </div>
      <script>var InitData = {"welcomeText":"Hello World :)"};</script>
      <script src="js/app.js"></script>
   </body>
</html>

The code that renders it:

import ReactDOM from "react-dom/server";
......
    res.end(ReactDOM.renderToStaticMarkup(
        <html>
            <head>
                <title>SSR POC</title>
            </head>
            <body>
                <div id="app" dangerouslySetInnerHTML={{__html: ReactDOM.renderToString(<div><h1>{data.welcomeText}</h1></div>)}}></div>
                <script dangerouslySetInnerHTML={{__html: 'var InitData = '+ JSON.stringify(data) +';'}}>
                </script>
                <script src="js/app.js"></script>
            </body>
        </html>
    ));

This is what gets rendered with react-dom-stream:

<html>
   <head>
      <title>SSR POC</title>
   </head>
   <body>
      <div id="app">
         <div data-reactid=".4wu0ivepkw">
            <h1 data-reactid=".4wu0ivepkw.0">Hello World :)</h1>
         </div>
         <script type="text/javascript" id=".4wu0ivepkw.script">
        if (!document.querySelector) throw new Error("react-dom-stream requires document.querySelector. If using IE8 or IE9, please make sure you are in standards mode by including <!DOCTYPE html>");
        document.querySelector('[data-reactid=".4wu0ivepkw"]').setAttribute("data-react-checksum", 1817648556);
        var s = document.getElementById(".4wu0ivepkw.script");
        s.parentElement.removeChild(s);
         </script>
      </div>
      <script>var InitData = {"welcomeText":"Hello World :)"};</script>
      <script src="js/app.js"></script>
   </body>
</html>

and the code that renders it:

import ReactDOMStream from "react-dom-stream/server";
........

    ReactDOMStream.renderToStaticMarkup(
        <html>
            <head>
                <title>SSR POC</title>
            </head>
            <body>
                <div id="app" dangerouslySetInnerHTML={{__html: ReactDOMStream.renderToString(<div><h1>{data.welcomeText}</h1></div>)}}></div>
                <script dangerouslySetInnerHTML={{__html: 'var InitData = '+ JSON.stringify(data) +';'}}>
                </script>
                <script src="js/app.js"></script>
            </body>
        </html>
    ).pipe(res);

Here are my dependencies:

  "dependencies": {
    "express": "^4.13.4",
    "react": "^15.0.1",
    "react-dom": "^15.0.1",
    "react-dom-stream": "^0.5.1",
    "react-raw-html": "^0.4.0"
  }

Let me know if I can help with something and thanks for the great work Sasha, Sam.

th0r commented 8 years ago

This package doesn't support React 15 yet... https://github.com/aickin/react-dom-stream/issues/18

aickin commented 8 years ago

Yeah, sorry for the delay, I've been hard at work trying to lay the groundwork for integrating streaming into react core.

As of now, react-dom-stream only works with React 0.14.x. If the PR I've been working on goes through, there will be a much more sustainable strategy for keeping streaming in React as React goes through upgrades, but it will require another rewrite of react-dom-stream. In that case, I think it's unlikely that React 15 will ever get streaming support. It's not worth it to me to update react-dom-stream for React 15 if the plan is to immediately dump the code base for React 16.

If my PR doesn't go through, I'll re-evaluate how best to support streaming going forward.

Thanks for your engagement, and please let me know if you have any questions or comments!

isaachinman commented 7 years ago

So is it safe to assume this package will never support React 15?

pedroBruno7 commented 5 years ago

Hi @aickin. Great job really ! I had similar problems with this project. I already read (after some time spent) that React already supports streams in version 16+. Could you update the read.me on the beginning with the compatibility of this project with React versions and a line saying this project is not needed anymore pointing to your article ? I think that would help a lot of people, if they stumble upon this project first like me. Big thanks