样式可能会持续50毫秒,然后在此SSR应用程序的以下代码中消失。我很好奇是什么原因造成的。
// This component is a child of index.tsx in the /pages folder
<Button
color="primary"
variant="outlined"
size="large"
>Test Button</Button>
样式消失后,剩下一个普通的HTML按钮。
我相信Next.js是造成这种情况的原因。我检查了Next.js文件,并将next / babel加载程序添加到.babelrc中。除此之外,我还看到了其他相关更改。这是在/pages/_document.js中:
MyDocument.getInitialProps = async ctx => {
const sheets = new MuiServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => sheets.collect(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
// Styles fragment is rendered after the app and page rendering finish.
styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
};
};
为解决问题所做的事情
没有更改。
没有变化。
理论
我认为服务器端存在问题。客户端和服务器应位于同一台计算机localhost上。这将解释正确的初始结果(客户端初始UI),然后由服务器更新覆盖。
更新1
忘了说我也确实更新了/pages/_app.js
。这是更新的部分:
class MyApp extends App {
componentDidMount() {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles && "parentElement" in jssStyles) {
(jssStyles.parentElement as HTMLElement).removeChild(jssStyles);
}
}
答案 0 :(得分:7)
对我来说,这个错误的根本原因是,在服务器的服务器端呈现期间生成的类与水合后生成的样式不匹配。
解决此问题的一种方法是在隐藏后强制重新渲染。
一种方法是更新组件上的关键道具。
// inside your component
const [key, setKey] = React.useState(0);
React.useEffect(() => {
setKey(1);
}, []);
return (<MyComponent key={}key />)
我的完整_app.tsx
文件:
import React from 'react';
import {
ThemeProvider,
createGenerateClassName,
StylesProvider
} from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import { darkTheme } from '../theme';
const generateClassName = createGenerateClassName({
productionPrefix: 'myclasses-'
});
export default function MyApp(props) {
const { Component, pageProps } = props;
const [key, setKey] = React.useState(0);
React.useEffect(() => {
setKey(1);
}, []);
React.useEffect(() => {
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<StylesProvider key={key} generateClassName={generateClassName}>
<React.Fragment>
<ThemeProvider theme={darkTheme}>
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</React.Fragment>
</StylesProvider>
);
}
答案 1 :(得分:1)
TLDR; 如果您正在运行生产版本,请确保将NODE_ENV设置为生产版本,例如:NODE_ENV=production npm start
对我来说,这仅是在使用npm run build
创建生产版本,然后使用npm start
运行生产版本时在我的机器上发生的。
奇怪的是,为什么服务器呈现的响应使用诸如makeStyles-root-123
之类的开发样式类而不是https://material-ui.com/styles/advanced/#class-names所解释的jss123
。
很显然,服务器的某些部分仍处于我们仍处于开发环境中的状态。为了解决这个问题,我尝试将NODE_ENV
设置为“ production”来开始生产构建,问题就解决了。
答案 2 :(得分:0)
暂时通过注释掉代码来删除服务器jssStyles
class MyApp extends App {
// componentDidMount() {
// // Remove the server-side injected CSS.
// const jssStyles = document.querySelector('#jss-server-side');
// if (jssStyles && "parentElement" in jssStyles) {
// (jssStyles.parentElement as HTMLElement).removeChild(jssStyles);
// }
// }
如果任何人都知道示例中为何包含此代码,请发表评论。一定有原因。 https://github.com/mui-org/material-ui/blob/master/examples/nextjs/pages/_app.js