React Material-ui SSR - 警告:道具“d”不匹配。服务器:"M 0 0 h 24 v 24 H 0 Z" 客户端:"M0 0h24v24H0z"
React Material-ui SSR - Warning: Prop `d` did not match. Server: "M 0 0 h 24 v 24 H 0 Z" Client: "M0 0h24v24H0z"
我正在使用服务器端呈现和 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"]
}
我遇到了类似的问题。这不是 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 />
}
对于 class 个组件,您将使用 componentDidMount
生命周期方法,而不是 setState
。
所以这看起来确实是 React 中的一个错误。我在 Material-ui 项目中记录了一个问题,该问题在 React 中导致了这个未解决的问题:
https://github.com/facebook/react/issues/15187
这个警告似乎是良性的,并且随着 Edge 转向 Chromium,我不再像以前那样担心了。
我遇到了同样的问题 ...不匹配服务器:...客户端:... 使用带有 Express.js 的 NextJS (React)服务器(节点server.js)。
解决方案是仅在 process.browser
为 true
时渲染组件。
{
process.browser ?
<MyComponent /> :
null
}
我正在使用服务器端呈现和 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"]
}
我遇到了类似的问题。这不是 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 />
}
对于 class 个组件,您将使用 componentDidMount
生命周期方法,而不是 setState
。
所以这看起来确实是 React 中的一个错误。我在 Material-ui 项目中记录了一个问题,该问题在 React 中导致了这个未解决的问题:
https://github.com/facebook/react/issues/15187
这个警告似乎是良性的,并且随着 Edge 转向 Chromium,我不再像以前那样担心了。
我遇到了同样的问题 ...不匹配服务器:...客户端:... 使用带有 Express.js 的 NextJS (React)服务器(节点server.js)。
解决方案是仅在 process.browser
为 true
时渲染组件。
{
process.browser ?
<MyComponent /> :
null
}