我不知道我的问题是 bug 还是仅仅是 support 术语,还是仅仅是 configuration 错误,但是我花了很多时间,不高兴去这里幸运地写给别人解决我的问题。不!
我搜索了3天,即使在这3天内仅睡了大约10个小时,还是尝试了多种方法,甚至我使用了Gitter,但没人回答我,我看到了问题#10982和{{3 }}和许多Stack Overflow
问题和答案,但我无法解决自己的问题,也找不到正确的方法。
当然,我读过Material-UI
#11506多次,但我完全按照文档所说的去做。
最后,我在服务器和客户端中看到类名水化不匹配,这是警告:
Warning: Prop `className` did not match. Server: "MuiFormLabel-root-134 MuiInputLabel-root-129 MuiInputLabel-formControl-130 MuiInputLabel-animated-133" Client: "MuiFormLabel-root-10 MuiInputLabel-root-5 MuiInputLabel-formControl-6 MuiInputLabel-animated-9"
我发誓我尝试了很多方法并进行了很多搜索。我正在使用Material-UI
版1.2.1
。
这是我的Index
组件,它是根组件:
import React, {Component} from 'react';
import Helmet from 'react-helmet';
import styles from 'StylesRoot/styles.pcss';
import TextField from '@material-ui/core/TextField';
export default class App extends Component {
render() {
return (
<div className={styles['root-wrapper']}>
<Helmet
htmlAttributes={{lang: 'fa', amp: undefined}}
bodyAttributes={{dir: 'rtl'}}
titleTemplate='اسکن - %s'
titleAttributes={{itemprop: 'name', lang: 'fa'}}
meta={[
{name: 'description', content: 'صفحه اتصال اعضاء'},
{name: 'viewport', content: 'width=device-width, initial-scale=1'},
]}
link={[{rel: 'stylesheet', href: '/dist/styles.css'}]}
/>
<TextField label='test' helperText='help'/>
</div>
);
};
}
在下面,您可以看到我的server.jsx
和client.jsx
:
//--------------------------------------------client.jsx
import React from 'react';
import {hydrate} from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import {MuiThemeProvider, createMuiTheme} from '@material-ui/core/styles';
import {lightBlue, red} from '@material-ui/core/colors';
import Index from './app/index';
import RTL from './app/public/rtl';
const theme = createMuiTheme({
palette: {
primary: lightBlue,
accent: red,
type: 'light',
},
direction: 'rtl',
});
class Main extends React.Component {
// Remove the server-side injected CSS.
componentDidMount() {
const jssStyles = document.getElementById('jss-server-side');
if (jssStyles && jssStyles.parentNode) {
jssStyles.parentNode.removeChild(jssStyles);
}
}
render() {
return (
<BrowserRouter>
<Index {...this.props}/>
</BrowserRouter>
);
}
}
hydrate((
<RTL>
<MuiThemeProvider theme={theme}>
<Main/>
</MuiThemeProvider>
</RTL>
), document.getElementById('root'));
//--------------------------------------------server.jsx
import React from 'react';
import {renderToString} from 'react-dom/server';
import {SheetsRegistry} from 'react-jss/lib/jss';
import JssProvider from 'react-jss/lib/JssProvider';
import {StaticRouter} from 'react-router-dom';
import {Helmet} from "react-helmet";
import {MuiThemeProvider, createMuiTheme, createGenerateClassName} from '@material-ui/core/styles';
import {red, lightBlue} from '@material-ui/core/colors';
import Template from './app/template';
import Index from './app/index';
import RTL from './app/public/rtl';
export default function serverRenderer({clientStats, serverStats}) {
return (req, res, next) => {
const context = {};
const sheetsRegistry = new SheetsRegistry();
const theme = createMuiTheme({
palette: {
primary: lightBlue,
accent: red,
type: 'light',
},
direction: 'rtl',
});
const generateClassName = createGenerateClassName();
const markup = renderToString(
<JssProvider registry={sheetsRegistry} generateClassName={generateClassName}>
<RTL>
<MuiThemeProvider theme={theme} sheetsManager={new Map()}>
<StaticRouter location={req.url} context={context}>
<Index/>
</StaticRouter>
</MuiThemeProvider>
</RTL>
</JssProvider>
);
const helmet = Helmet.renderStatic();
const jss = sheetsRegistry.toString();
res.status(200).send(Template({
markup: markup,
helmet: helmet,
jss: jss,
}));
};
}
所以现在需要template.jsx
:
export default ({ markup, helmet, jss }) => {
return `<!DOCTYPE html>
<html ${helmet.htmlAttributes.toString()}>
<head>
${helmet.title.toString()}
${helmet.meta.toString()}
${helmet.link.toString()}
<style id='jss-server-side'>${jss}</style>
</head>
<body ${helmet.bodyAttributes.toString()}>
<div id='root'>${markup}</div>
<script src='/dist/client.js' async></script>
</body>
</html>`;
};
好吧,现在可能会问这个问题 RTL
是什么?和为什么在服务器和客户端中都将MuiThemeProvider
包裹在其中?< / em>
因此,首先请参见RTL
组件:
import React from 'react';
import {create} from 'jss';
import rtl from 'jss-rtl';
import JssProvider from 'react-jss/lib/JssProvider';
import {createGenerateClassName, jssPreset} from '@material-ui/core/styles';
const jss = create({plugins: [...jssPreset().plugins, rtl()]});
const generateClassName = createGenerateClassName();
export default props => (
<JssProvider jss={jss} generateClassName={generateClassName}>
{props.children}
</JssProvider>
);
我在Material-UI
Docs中看到了它,并且我认为文档有点差,可以改进。我问自己,为什么文档为此功能传递props.children
?,我想也许这个功能应该包装一些东西。所以我尝试了多种形状,而且效果很好。但是在构建后在浏览器中的第一个调用中。当我刷新浏览器时,警告出现,并且我看到该死的形状:
我当然想看到下面的形状,但是在构建后只看到一次:
我不知道怎么了。我也在Docs上留下了一个问题。并为此问题上载Github
,仅查看pull
,然后先运行npm install
然后运行num run dev
。该项目可以在mini repo
答案 0 :(得分:0)
我不知道这种方法是否正确,但是它很好用,实际上,我发现使用单独的rtl.jsx
组件不是一个好方法,这导致服务器和客户端之间的不一致,我分别为每个服务器端和客户端使用Right-to-Left文档页面,因此从我的项目中省略了server.jsx
文件及其组件,所以client.jsx
和//---------------------------------------------client.jsx
import React, {Component} from 'react';
import {hydrate} from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import {
MuiThemeProvider, createMuiTheme,
createGenerateClassName, jssPreset
} from '@material-ui/core/styles';
import {create} from 'jss';
import rtl from 'jss-rtl';
import JssProvider from 'react-jss/lib/JssProvider';
import {lightBlue, red} from '@material-ui/core/colors';
import Index from './app/index';
const theme = createMuiTheme({
palette: {
primary: lightBlue,
accent: red,
type: 'light',
},
direction: 'rtl',
});
const jssRTL = create({plugins: [...jssPreset().plugins, rtl()]});
const generateClassName = createGenerateClassName();
class Main extends Component {
componentDidMount() {
const jssStyles = document.getElementById('jss-server-side');
if (jssStyles) {
jssStyles.remove();
}
}
render() {
return (
<BrowserRouter>
<Index {...this.props}/>
</BrowserRouter>
);
}
}
hydrate((
<JssProvider jss={jssRTL} generateClassName={generateClassName}>
<MuiThemeProvider theme={theme}>
<Main/>
</MuiThemeProvider>
</JssProvider>
), document.getElementById('root'));
//---------------------------------------------server.jsx
import React from 'react';
import {renderToString} from 'react-dom/server';
import {SheetsRegistry} from 'react-jss/lib/jss';
import JssProvider from 'react-jss/lib/JssProvider';
import {StaticRouter} from 'react-router-dom';
import {Helmet} from "react-helmet";
import {
MuiThemeProvider, createMuiTheme,
createGenerateClassName, jssPreset
} from '@material-ui/core/styles';
import {create} from 'jss';
import rtl from 'jss-rtl';
import {red, lightBlue} from '@material-ui/core/colors';
import Template from './app/template';
import Index from './app/index';
export default function serverRenderer({clientStats, serverStats}) {
return (req, res, next) => {
const context = {};
const sheetsRegistry = new SheetsRegistry();
const theme = createMuiTheme({
palette: {
primary: lightBlue,
accent: red,
type: 'light',
},
direction: 'rtl',
});
const jssRTL = create({plugins: [...jssPreset().plugins, rtl()]});
const generateClassName = createGenerateClassName();
const markup = renderToString(
<JssProvider jss={jssRTL}
registry={sheetsRegistry}
generateClassName={generateClassName}>
<MuiThemeProvider theme={theme} sheetsManager={new Map()}>
<StaticRouter location={req.url} context={context}>
<Index pathname={req.url}/>
</StaticRouter>
</MuiThemeProvider>
</JssProvider>
);
const helmet = Helmet.renderStatic();
const jss = sheetsRegistry.toString();
res.status(200).send(Template({
markup: markup,
helmet: helmet,
jss: jss,
}));
};
}
就像下方:
Material-UI
它在服务器和客户端上都可以很好地工作,并且在样式标签中使CSS
{{1}}保持一致。