在_document之外使用Next.jsHead组件会导致页面崩溃

我正在尝试将Next.jsTypescriptMaterial 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 中的代码完成提示了错误的包含。


以上是在_document之外使用Next.jsHead组件会导致页面崩溃的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>