在_document之外使用Next.jsHead组件会导致页面崩溃
我正在尝试将Next.js与Typescript和Material UI一起使用。有无数的在线教程如何Next.js设立工作,材料UI,和所有的人似乎可以用完全一样的代码_document.js,并_app.js分别。
我已经尝试将代码_document.js稍微调整为打字稿_document.tsx,并按原样复制粘贴它,但每次我遇到同样的问题,即每当我尝试使用<Head />外部_document.tsx,甚至只是内部_app.tsx来设置一个标题和视口元,正如教程中的代码所暗示的那样,我收到了一条非常无用的错误消息(下面包含完整的堆栈跟踪):
TypeError: Cannot destructure property 'styles' of 'this.context' as it is null.
我在我之前的一个项目中遇到了完全相同的问题,这就是为什么我既惊讶又沮丧的是,似乎没有人与我有同样的问题,而且我能找到的每个教程都包含完全相同的代码似乎对我不起作用。
这是我的代码:
_document.tsx
import React from "react";
import Document, { DocumentContext, DocumentInitialProps, Head, Html, Main, NextScript } from "next/document";
import { ServerStyleSheets } from "@material-ui/core/styles";
import theme from "../constants/theme";
class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
<meta name="theme-color" content={theme.palette.primary.main} />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
const sheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () => originalRenderPage({
enhanceApp: (App) => (props) => sheets.collect(<App {...props} />)
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()]
}
}
}
export default MyDocument;
_app.tsx
import { CssBaseline, ThemeProvider } from "@material-ui/core";
import { Head } from "next/document";
import React from "react"
import theme from "../constants/theme";
function MyApp({ Component, pageProps }) {
React.useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) jssStyles.parentElement.removeChild(jssStyles);
}, []);
return (
<React.Fragment>
<Head>
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<ThemeProvider theme={theme}>
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</React.Fragment>
)
}
export default MyApp
如果需要,我很乐意提供更多信息,但由于我真的不明白问题是什么,我真的不知道哪些部分与此处发布相关。
这是我得到的错误的完整堆栈跟踪:
TypeError: Cannot destructure property 'styles' of 'this.context' as it is null.
at Head.render (E:devweblore-web.nextserverpages_document.js:484:7)
at processChild (E:devweblore-webnode_modulesreact-domcjsreact-dom-server.node.development.js:3450:18)
at resolve (E:devweblore-webnode_modulesreact-domcjsreact-dom-server.node.development.js:3270:5)
at ReactDOMServerRenderer.render (E:devweblore-webnode_modulesreact-domcjsreact-dom-server.node.development.js:3753:22)
at ReactDOMServerRenderer.read (E:devweblore-webnode_modulesreact-domcjsreact-dom-server.node.development.js:3690:29)
at renderToString (E:devweblore-webnode_modulesreact-domcjsreact-dom-server.node.development.js:4298:27)
at renderPage (E:devweblore-webnode_modulesnextdistnext-serverserverrender.js:54:851)
at Object.ctx.renderPage (E:devweblore-web.nextserverpages_document.js:963:28)
at Function.getInitialProps (E:devweblore-web.nextserverpages_document.js:310:19)
at Function.getInitialProps (E:devweblore-web.nextserverpages_document.js:971:85)
at loadGetInitialProps (E:devweblore-webnode_modulesnextdistnext-serverlibutils.js:5:101)
at renderToHTML (E:devweblore-webnode_modulesnextdistnext-serverserverrender.js:54:1142) at async E:devweblore-webnode_modulesnextdistnext-serverservernext-server.js:107:97
at async E:devweblore-webnode_modulesnextdistnext-serverservernext-server.js:100:142
at async DevServer.renderToHTMLWithComponents (E:devweblore-webnode_modulesnextdistnext-serverservernext-server.js:132:387)
at async DevServer.renderToHTML (E:devweblore-webnode_modulesnextdistnext-serverservernext-server.js:133:522)
回答
Head 需要从“next/head”而不是“next/document”导入。在文档中看到这里:https : //nextjs.org/docs/api-reference/next/head
但是,这一次您必须使用默认导入:
import Head from "next/head";
_app.tsx 需要做相应的调整:
import { CssBaseline, ThemeProvider } from "@material-ui/core";
import Head from "next/head";
import React from "react"
import theme from "../constants/theme";
function MyApp({ Component, pageProps }) {
React.useEffect(() => {
const jssStyles = document.querySelector("#jss-server-side");
if (jssStyles) jssStyles.parentElement.removeChild(jssStyles);
}, []);
return (
<React.Fragment>
<Head>
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<ThemeProvider theme={theme}>
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</React.Fragment>
)
}
export default MyApp
我也遇到过这个问题,因为 WebStorm 中的代码完成提示了错误的包含。