我正在使用服务器端渲染和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"]
}
答案 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.browser
为true
的情况下呈现组件。
{
process.browser ?
<MyComponent /> :
null
}