Warning: React attempted to reuse markup in a container but the checksum was invalid

試著忘記壹切 提交于 2019-11-27 17:50:43

Note: This applies to older versions of React. If you're using React 16, you should use ReactDOM.hydrate()

Also, the below suggestion will result in a client-side re-render, as suggested by one of the answers below.


This may sound crazily simple, but in your server-side template, wrap your React markup in an extra <div>:

<!-- hypothetical handlebars template -->
<section role="main" class="react-container"><div>{{{reactMarkup}}}</div></section>

Why does this work? On the client, React has a propensity to wrap its rendering of your root component with a superfluous div. ReactDOMServer.render doesn't seem to behave in this manner, thus when one renders into the same container isomorphically, the Adler-32 checksum of your DOM differs.

For those googling and coming here, one weird way of ending up with this issue is where you're not even using isomorphic rendering (i.e. not rendering anything on the server side). This happened with me when using a template with the HtmlWebpackPlugin to process an index.html file.

In my index.html file I already included the bundle.js file myself, and the above plugin also includes another bundle.js via a script-src. Make sure you're setting inject: false to your HtmlWebpackPlugin constructor.

For me killing nodejs completely and restarting worked

WARNING The popular answer here is not correct. What it is doing is removing the existing DOM entirely, and replacing it with a fresh render on the client. It means you lose the fast shallow render from React and are wasting perf, and as a consequence it also swallows the OP error, and any other errors you might have.

Your issue appears to be with CSS - if you are using autoprefixer and inline-styles that would explain your difference here.

The server side has rendered align-items:center and the client has realised it's in a webkit browser and automatically prefixed it for you to -webkit-align-items.

Please post more info about the CSS set up, and any component using inline-styles or similar.

If you are rendering your main content inside of a layout component, you will need to render the layout as static markup (no react attributes) so that the checksum of the content matches between the client and server.

Server:

app.get('/', (req, res) => {
  // render the content to a string so it has the same checksum as on the client
  // render the layout to static markup so that it does affect the checksum
  // this ensures that rendering is isomorphic and client doesn't override server markup
  const content = reactDomServer.renderToString(<MyContent />)
  const html = '<!DOCTYPE html>' + reactDomServer.renderToStaticMarkup(<HtmlLayout content={content} />)
  res.send(html)
})

HtmlLayout:

export default class HtmlLayout extends React.Component<any, any> {
  public render () {
    return (
      <html lang='en'>
      <head>
        <meta charSet='utf-8' />
        <meta name='viewport' content='width=device-width, initial-scale=1' />
        <title>Untitled</title>
        <link rel='stylesheet' href='/style/bundle.css' />
      </head>
      <body>
        { /* insert the content as a string so that it can be rendered separate with its own checksum for proper server-side rendering */ }
        <div id='content' dangerouslySetInnerHTML={ {__html: this.props.content} } />
        <script src='scripts/bundle.js'></script>
      </body>
      </html>
    )
  }
}

Client:

const root = document.getElementById('content')    
DOM.render(<MyContent />, root)

Reference: http://jeffhandley.github.io/QuickReactions/20-final-cleanup

In my case the problem was caused by the fact that I was using MediaQuery component from 'react-responsive' without passing the 'value' property which is used by the component when it is not able to access the screen width (e.g. on the Server).

I came across this issue on an Isomorphic app I was working on. What worked for me is, believe it or not, Emptying cache and hard reloading the app on Chrome. Looked like the old DOM was somehow cached on the Browser :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!