Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Text content did not match. Warning in React 16

I trying to build ReactJs application with server side rendering My entry points for client and server:

client.jsx

const store = createStore(window.__INITIAL_STATE__);

hydrate(
  <Provider store={store}>
    <BrowserRouter>{renderRoutes(routes)}</BrowserRouter>
  </Provider>,
  document.querySelector('#root')
);

server.jsx

const app = express();

if (isDev) {
  const webpack = require('webpack');
  const webpackDevMiddleware = require('webpack-dev-middleware');
  const config = require('../../webpack.config.js');
  const compiler = webpack(config);

  app.use(express.static('/public'));
  app.use(
    webpackDevMiddleware(compiler, {
      publicPath: config.output.publicPath,
      stats: 'errors-only',
    })
  );
}

app.get('*', (req, res) => {
  const helmet = Helmet.renderStatic();
  const htmlAttrs = helmet.htmlAttributes.toComponent();
  const bodyAttrs = helmet.bodyAttributes.toComponent();

  const context = {};
  const data = {};

  res.set('content-type', 'text/html');

  res.send(
    '<!DOCTYPE html>' +
      renderToString(
        <html {...htmlAttrs}>
          <head>
            {helmet.title.toComponent()}
            {helmet.meta.toComponent()}
            {helmet.link.toComponent()}
          </head>
          <body {...bodyAttrs}>
            <div id="root">
              <StaticRouter location={req.url} context={context}>
                {renderRoutes(routes)}
              </StaticRouter>
            </div>
            <script
              dangerouslySetInnerHTML={{
                __html: `window.__INITIAL_STATE__ = ${JSON.stringify(data)}`,
              }}
            />
            <script src="/public/vendor.js" />
            <script src="/public/app.js" />
          </body>
        </html>
      )
  );
});

And component:

home.jsx

import React, { Component } from 'react';

class Home extends Component {
  render() {
    return <div>home</div>;
  }
}

export default Home;

When I change in my component Home and refresh browser page I get this error:

Warning: Text content did not match. Server: "home" Client: "home1"

Its ok because server render old version of my code. How to reload the code on the server so that the client and server versions are equal?

like image 716
Pavel Avatar asked Nov 17 '17 11:11

Pavel


2 Answers

For those discovering this error because your client and server purposefully render different content (like the server rendering a dark theme which gets replaced with the user preference on load), use suppressHydrationWarning to suppress the error.

For example:

<div suppressHydrationWarning>Ignore this</div>
like image 137
Cyral Avatar answered Nov 14 '22 12:11

Cyral


The problem here is that your server-side application does not reflect code changes. To do that you have to configure your express app as a webpack entry.

Briefly, you need 2 webpack configurations one for server and another for client code. The server one will look something like this

module.exports = {
  entry: {
    server: './server.js',
  },
  output: {
    path: path.join(__dirname, 'dist'),
    publicPath: '/',
    filename: '[name].js'
  },
  target: 'node',
  node: {
    // Need this when working with express, otherwise the build fails
    __dirname: false,   // if you don't put this is, __dirname
    __filename: false,  // and __filename return blank or /
  },
  externals: [nodeExternals()], // Need this to avoid error when working with Express
  module: {
    rules: [
      {
        // Transpiles ES6-8 into ES5
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        // Loads the javacript into html template provided.
        // Entry point is set below in HtmlWebPackPlugin in Plugins 
        test: /\.html$/,
        use: [{loader: "html-loader"}]
      }
    ]
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: "./index.html",
      filename: "./index.html",
      excludeChunks: [ 'server' ]
    })
  ]
}

Here is a nice article explaining how to do that in details

like image 39
mpospelov Avatar answered Nov 14 '22 12:11

mpospelov