Nextjs throwing classnames do not match error when using babel-plugin-styled-components

151 views Asked by At

I have copied over the _document.js from the next styled components example and I am using the babel plugin from the styled components docs, but I am still getting the error.

_document.js

import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
    static async getInitialProps(ctx) {
        const sheet = new ServerStyleSheet()
        const originalRenderPage = ctx.renderPage

        try {
            ctx.renderPage = () =>
                originalRenderPage({
                    enhanceApp: (App) => (props) =>
                        sheet.collectStyles(<App {...props} />),
                })

            const initialProps = await Document.getInitialProps(ctx)
            return {
                ...initialProps,
                styles: (
                    <>
                        {initialProps.styles}
                        {sheet.getStyleElement()}
                    </>
                ),
            }
        } finally {
            sheet.seal()
        }
    }
}

.babelrc

{
    "presets": [
        "next/babel"
    ],
    "plugins": [
        [
            "babel-plugin-styled-components"
        ]
    ]
}

Just started using next on wednesday so still fairly new with the technology, but I've looked through all the docs and this seems to be what is supposed to work, but I am still getting the error, any thoughts?

1

There are 1 answers

0
Andrew Ross On

You aren't rendering() then returning () any jsx. That's your issue here most likely. You should also be importing Html, Head, Main, and NextScript from "next/document".

To resolve your issue, try refactoring as follows:

import Document { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet } from 'styled-components';

export default class MyDocument extends Document {
    static async getInitialProps(ctx) {
        const sheet = new ServerStyleSheet();
        const originalRenderPage = ctx.renderPage;

        try {
            ctx.renderPage = () =>
                originalRenderPage({
                    enhanceApp: (App) => (props) =>
                        sheet.collectStyles(<App {...props} />),
                });

            const initialProps = await Document.getInitialProps(ctx);
            return {
                ...initialProps,
                styles: (
                    <>
                        {initialProps.styles}
                        {sheet.getStyleElement()}
                    </>
                )
            };
        } finally {
            sheet.seal()
        }
    }
   render() {
        return (
            <Html lang='en'>
                <Head>
                    <meta charSet='utf-8' />
                    {this.props.styles}
                </Head>
                <body>
                    <Main />
                    <NextScript />
                </body>
            </Html>
        );
   } 
}

Then in _app.jsx you will import { ThemeProvider } from styled-components. ThemeProvider wraps the custom styled-components GlobalTheme JSX Element imported from another file. The following snippet is in typescript from a project I built a couple months ago. Most is relevant with the exception of the AppProps tidbit:

import Head from "next/head";
import { AppProps } from "next/app";
import { ThemeProvider } from "styled-components";
import { GlobalStyle, theme } from "../shared";

export default function App({ Component, pageProps }: AppProps) {
    return (
        <ThemeProvider theme={theme}>
            <GlobalStyle theme={theme} />
            <Head>
                <title>Next.js</title>
            </Head>
            <main className="main">
               <Component {...pageProps} />
            </main>
        </ThemeProvider>
    )
}