React Material-ui SSR-警告:道具d不匹配。服务器:“ M 0 0 h 24 v 24 H 0 Z”客户端:“ M0 0h24v24H0z”

时间:2019-03-20 23:56:37

标签: reactjs internet-explorer-11 material-ui microsoft-edge ssr

我正在使用服务器端渲染和Material-ui的React网站上工作。包括mui JSS在内的所有东西都运行良好。

然后我从@ material-ui / icons添加了一个SVG图标

现在,Edge和IE11抱怨: 警告:道具d不匹配。服务器:“ M 0 0 h 24 v 24 H 0 Z”客户端:“ M0 0h24v24H0z”

警告表明服务器和客户端的渲染不匹配,但是如果我使用curl获取服务器渲染,那是正确的,并且不包括IE / Edge控制台中显示的空格。

(当然)所有其他浏览器都可以。

还有其他人仅在MS浏览器中遇到过SSR问题吗?

这是我所举的例子。它基于material-ui-master / examples / ssr,其中删除了大部分内容:

server.js:

import express from "express";
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import App from './App';

function renderFullPage(html) {
  return `
    <!doctype html>
    <html>
      <body>
        <div id="root">${html}</div>
        <script src="build/bundle.js"></script>
      </body>
    </html>
  `;
}

function handleRender(req, res) {
  // Render the component to a string.
  const html = ReactDOMServer.renderToString(
        <App />
  );

  res.send(renderFullPage(html));
}

const app = express();

app.use('/build', express.static('build'));

// This is fired every time the server-side receives a request.
app.use(handleRender);

const port = 3000;
app.listen(port);

client.js:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

class Main extends React.Component {
  render() {
    return <App />;
  }
}

ReactDOM.hydrate(
  <Main />
  , document.querySelector('#root')
);

App.js:

import React from 'react';
import { Menu } from "@material-ui/icons";

export default class App extends React.Component {
  render() {
    return (
      <Menu />
    );
  }
}

package.json:

{
  "name": "ssr",
  "version": "3.0.0",
  "private": true,
  "dependencies": {
    "@babel/core": "latest",
    "@babel/node": "latest",
    "@babel/plugin-proposal-class-properties": "latest",
    "@babel/preset-env": "^7.4.2",
    "@babel/preset-react": "latest",
    "@material-ui/core": "latest",
    "@material-ui/icons": "^3.0.2",
    "babel-loader": "next",
    "express": "latest",
    "fs": "0.0.1-security",
    "net": "^1.0.2",
    "nodemon": "latest",
    "prop-types": "latest",
    "react": "latest",
    "react-dom": "latest",
    "react-jss": "^8.1.0",
    "webpack": "latest",
    "webpack-cli": "latest"
  },
  "scripts": {
    "start-server": "SET NODE_ENV=development& nodemon --inspect ./build/server.js",
    "start": "webpack -w"
  }
}

webpack.config.js:

const path = require('path');

const browserConfig = {
  entry: './client.js',
  node: {
    fs: "empty"
  },
  mode: process.env.NODE_ENV || 'development',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js',
    publicPath: '/',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
    ],
  },
};

const serverConfig = {
  entry: './server.js',
  target: 'node',
  node: {
    fs: "empty"
  },
  mode: process.env.NODE_ENV || 'development',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'server.js',
    publicPath: '/',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
    ],
  },
};

module.exports = [browserConfig, serverConfig]

.babel.rc:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}

3 个答案:

答案 0 :(得分:0)

我有一个类似的问题。这不是SSR的问题,而是JSX中的条件渲染,其中条件在服务器和客户端上都不同。

在我的情况下,我根据从localStorage读取的条件(仅在客户端上定义)渲染了某些内容。在服务器上,它返回了undefined,因此客户端和服务器上呈现的内容不匹配。

在我的案例中,解决方案是根据组件是否在客户端上渲染而有条件地渲染。

我写了以下自定义钩子:

import {useEffect, useState} from "react";

export const useLoaded = () => {
    const [loaded, setLoaded] = useState(false);
    useEffect(() => setLoaded(true), []);
    return loaded;
};

我是这样使用的:

// in the functional component's body
const loaded = useLoaded();

// in the JSX
{localCondition && loaded &&
  <MyComponent />
}

对于类组件,您将使用componentDidMount生命周期方法,而使用setState

答案 1 :(得分:0)

所以这似乎是React中的错误。我将一个问题记录到Material-ui项目中,导致在React中出现了这个未解决的问题:

https://github.com/facebook/react/issues/15187

警告似乎是无害的,并且Edge移到了Chromium,我不再像以前那样担心了。

答案 2 :(得分:0)

我遇到了相同的问题 ...与服务器:...客户端:... 不匹配,将NextJS(React)与Express.js服务器(节点server.js)一起使用

解决方案是仅在process.browsertrue的情况下呈现组件。

{
  process.browser ?
  <MyComponent /> :
  null
}