Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting ReactDOMServer does not yet support Suspense error while using styled-components #22508

Closed
pdugan20 opened this issue Feb 24, 2021 · 18 comments
Labels
bug Issue was opened via the bug report template.

Comments

@pdugan20
Copy link

pdugan20 commented Feb 24, 2021

What version of Next.js are you using?

10.0.6

What version of Node.js are you using?

14.4.0

What browser are you using?

Firefox

What operating system are you using?

Mac

How are you deploying your application?

Heroku

Describe the Bug

I recently updated next-i18next to 8.0.0 and am also using styled components with a custom _document.js as described in the nextjs examples section (https://github.com/vercel/next.js/tree/master/examples/with-styled-components).

If I load my page index and navigate to another page like /about, everything works fine. If I try to navigate directly to /about, I get the following error:
Error: ReactDOMServer does not yet support Suspense.

Expected Behavior

I would expect to be able to load other pages directly without an error appearing.

To Reproduce

Code snippets below in the comments.

The error I'm getting is:
Error: ReactDOMServer does not yet support Suspense.

Screen Shot 2021-02-24 at 12 34 34 PM

Here's an example of _document.js

import React from 'react';
import PropTypes from 'prop-types';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet as StyledComponentsSheet } from 'styled-components';
import { ServerStyleSheets as MaterialUiSheets } from '@material-ui/core/styles';

const { NEXT_PUBLIC_GA_TRACKING_ID } = process.env;

const propTypes = {
    lang: PropTypes.string,
};

const defaultProps = {
    lang: 'en',
};

class MyDocument extends Document {
    static async getInitialProps(ctx) {
        const styledComponentsSheet = new StyledComponentsSheet();
        const materialUiSheets = new MaterialUiSheets();
        const originalRenderPage = ctx.renderPage;

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

            const initialProps = await Document.getInitialProps(ctx);

            return {
                ...initialProps,
                styles: [
                    <React.Fragment key='styles'>
                        {initialProps.styles}
                        {materialUiSheets.getStyleElement()}
                        {styledComponentsSheet.getStyleElement()}
                    </React.Fragment>,
                ],
            };
        } finally {
            styledComponentsSheet.seal();
        }
    }

    render() {
        const { lang } = this.props;

        return (
            <Html lang={lang}>
                <Head>
                    <script
                        async
                        src={`https://www.googletagmanager.com/gtag/js?id=${NEXT_PUBLIC_GA_TRACKING_ID}`}
                    />
                    <script
                        async
                        src='https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js'
                    />
                    <script
                        dangerouslySetInnerHTML={{
                            __html: `window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);} gtag('js',new Date());gtag('config','${NEXT_PUBLIC_GA_TRACKING_ID}',{page_path:window.location.pathname,});`,
                        }}
                    />
                </Head>
                <body>
                    <Main />
                    <NextScript />
                    <script> </script>
                </body>
            </Html>
        );
    }
}

MyDocument.propTypes = propTypes;
MyDocument.defaultProps = defaultProps;

export default MyDocument;

Here's an example of a page:

import React from 'react';
import PropTypes from 'prop-types';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { RichText } from 'prismic-reactjs';
import Page from '../layouts/main';
import { getPageData } from '../utils/page';
import IntroSection from '../components/about/section/Intro';
import MapSection from '../components/about/section/Map';
import FooterSection from '../components/landing/section/Footer';
import { RootView } from '../styles/page';

const propTypes = {
    title: PropTypes.array.isRequired,
    description: PropTypes.array.isRequired,
};

const AboutPage = ({ title, description }) => {
    title = JSON.parse(title);
    description = JSON.parse(description);

    const renderMainColumn = () => {
        return (
            <RootView>
                <IntroSection title={title} description={description} />
                <MapSection />
                <FooterSection />
            </RootView>
        );
    };

    return (
        <Page
            singleColumn
            fullWidth
            title={RichText.asText(title)}
            mainColumn={renderMainColumn()}
        />
    );
};

export async function getServerSideProps({ req, locale }) {
    const page = await getPageData(req, locale, 'about');

    return {
        props: {
            title: JSON.stringify(page.data.title),
            description: JSON.stringify(page.data.description),
            ...(await serverSideTranslations(locale, [
                'about',
                'common',
                'header',
                'footer',
            ])),
        },
    };
}

AboutPage.propTypes = propTypes;

export default AboutPage;
@pdugan20 pdugan20 added the bug Issue was opened via the bug report template. label Feb 24, 2021
@pdugan20 pdugan20 changed the title Getting ReactDOMServer does not yet support Suspense while using styled-components Getting ReactDOMServer does not yet support Suspense error while using styled-components Feb 24, 2021
@pdugan20
Copy link
Author

I see this mentioned here without resolution: #16216

@jasondibenedetto
Copy link

Also getting this error at the moment

@mario-ls
Copy link

mario-ls commented Mar 5, 2021

I have the same bug with:

@mario-ls
Copy link

mario-ls commented Mar 5, 2021

It seems that adding the below settings to next-i18next-config.js is solving the problem:

react: {
  useSuspense: false,
  wait: true
}

@SalahAdDin
Copy link

It seems that adding the below settings to next-i18next-config.js is solving the problem:

react: {
  useSuspense: false,
  wait: true
}

Is it suspected to be like that? useSuspense, which function does it has here?

@pdugan20
Copy link
Author

pdugan20 commented Mar 8, 2021

Passing in useSuspense: false even without passing wait: true solved this for me.

@pdugan20 pdugan20 closed this as completed Mar 8, 2021
@jamesryan-dev
Copy link

Could someone paste a working example please of the suggested fix as I can't work out how to add this to a next.config.js

Current implementation:

const plugins = require('next-compose-plugins')
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})

const withOffline = require('next-offline')
const path = require('path')

function esbuildLoader(config, options) {
  const jsLoader = config.module.rules.find(
    (rule) => rule.test && rule.test.test('.js')
  )
  if (jsLoader && jsLoader.use) {
    if (jsLoader.use.length > 0) {
      jsLoader.use.forEach((e) => {
        e.loader = 'esbuild-loader'
        e.options = options
      })
    } else {
      jsLoader.use.loader = 'esbuild-loader'
      jsLoader.use.options = options
    }
  }
}

// the config break if we use next export
const nextConfig =
  process.env.EXPORT !== 'true'
    ? {
        webpack(config, { webpack, dev }) {
          config.plugins.push(
            new webpack.ProvidePlugin({
              React: 'react',
            })
          )
          // if you want to do a custom build to reduce the size of threejs <-- this require webpack and path
          config.plugins.unshift(
            new webpack.NormalModuleReplacementPlugin(
              /three.module.js/,
              path.resolve('src/examples/three_builds/three_minimal.js')
            )
          )
          // use esbuild in dev for faster HMR
          if (dev) {
            esbuildLoader(config, {
              loader: 'jsx',
              target: 'es2017',
            })
            // config.optimization.minimizer.shift()
          }

          config.module.rules.push(
            { test: /react-spring/, sideEffects: true }, // prevent vercel to crash when deploy
            {
              test: /\.(glsl|vs|fs|vert|frag)$/,
              exclude: /node_modules/,
              use: ['raw-loader', 'glslify-loader'],
            }
          )

          return config
        },
      }
    : {}

// manage i18n
if (process.env.EXPORT !== 'true') {
  nextConfig.i18n = {
    locales: ['en-US'],
    defaultLocale: 'en-US',
    react: {
      useSuspense: false,
      wait: true,
    },
  }
}

module.exports = plugins(
  [
    [
      withOffline,
      {
        workboxOpts: {
          swDest: process.env.NEXT_EXPORT
            ? 'service-worker.js'
            : 'static/service-worker.js',
          runtimeCaching: [
            {
              urlPattern: /^https?.*/,
              handler: 'NetworkFirst',
              options: {
                cacheName: 'offlineCache',
                expiration: {
                  maxEntries: 200,
                },
              },
            },
          ],
        },
        async rewrites() {
          return [
            {
              source: '/service-worker.js',
              destination: '/_next/static/service-worker.js',
            },
          ]
        },
      },
    ],
    withBundleAnalyzer,
  ],
  nextConfig
)

Sourced from react-three-fibre next.js starter

@SalahAdDin
Copy link

@jamesryan-dev did you try with:

It seems that adding the below settings to next-i18next-config.js is solving the problem:

react: {
  useSuspense: false,
  wait: true
}

@jamesryan-dev
Copy link

Hey @SalahAdDin

I kinda did..

I have the next-i18next-config.js at the root of my directory simply containing:

react: {
  useSuspense: false,
  wait: true
}

Had to yarn add the package but other than those two steps I wasn't sure what else to do - if anything..

@jamesryan-dev
Copy link

I assumed what with inheriting this config that adding the solution within the i18n section of this pre-cooked config would be correct no?

// manage i18n
if (process.env.EXPORT !== 'true') {
  nextConfig.i18n = {
    locales: ['en-US'],
    defaultLocale: 'en-US',
    react: {
      useSuspense: false,
      wait: true,
    },
  }
}

@SalahAdDin
Copy link

That's how i'm using it:

module.exports = {
  i18n: {
    localeDetection: false,
    defaultLocale: "en",
    locales: ["en", "es", "tr"],
  },
  react: {
    useSuspense: false,
    wait: true,
  },
};

@gsambrotta
Copy link

That's how i'm using it:

module.exports = {
  i18n: {
    localeDetection: false,
    defaultLocale: "en",
    locales: ["en", "es", "tr"],
  },
  react: {
    useSuspense: false,
    wait: true,
  },
};

In which file did you wrote this?

I use next-traslate and in my i18n.js file (so not my next.config.js) I have this:

module.exports = {
  locales: ['en', 'it'],
  defaultLocale: 'en',
  pages: {
    '*': ['common'],
    '/': ['home'],
    '/about': ['about'],
    '/new-about': ['about'],
    '/terms': ['terms'],
    '/privacy': ['privacy'],
    '/search': ['search'],
  },
  react: {
    useSuspense: false,
    wait: true,
  },
  staticsHoc: require('hoist-non-react-statics'),
}

but no luck. Anyone using next-translate maybe?

@SalahAdDin
Copy link

That's how i'm using it:

module.exports = {
  i18n: {
    localeDetection: false,
    defaultLocale: "en",
    locales: ["en", "es", "tr"],
  },
  react: {
    useSuspense: false,
    wait: true,
  },
};

In which file did you wrote this?

I use next-traslate and in my i18n.js file (so not my next.config.js) I have this:

module.exports = {
  locales: ['en', 'it'],
  defaultLocale: 'en',
  pages: {
    '*': ['common'],
    '/': ['home'],
    '/about': ['about'],
    '/new-about': ['about'],
    '/terms': ['terms'],
    '/privacy': ['privacy'],
    '/search': ['search'],
  },
  react: {
    useSuspense: false,
    wait: true,
  },
  staticsHoc: require('hoist-non-react-statics'),
}

but no luck. Anyone using next-translate maybe?

I'm using next-i18n, i followed the instructions, i put that configuration in a file apart, and it does work for me, for now.

@adrianbienias
Copy link
Contributor

adrianbienias commented May 12, 2021

In my case following error
Error: ReactDOMServer does not yet support Suspense.
was caused by using useTranslation() with the wrong string (non existing i18n file) as an argument

So at the end of the day next-i18next

const { t } = useTranslation("fileThatDoesNotExist")

causes veeeeery vague error

@pjchender
Copy link

pjchender commented May 12, 2021

@adrianbienias You are right. Also, it only occurred when the page is launch directly but not navigate from other pages, and I think this issue has nothing to do with styled-components or _document.js.

But I think this is only one kind of situation this might happen.

@herbievine
Copy link

I'm not using any kind of translation package... Is there any fix for a next.config.js?

@m-sterspace
Copy link

Also, it only occurred when the page is launch directly but not navigate from other pages, and I think this issue has nothing to do with styled-components or _document.js.

I don't think it has anything to do with styled-components, but I do suspect there's something wrong with _document.js.

Similarly to @mario-ls, I'm using the _document.js for Material UI and am getting the same error. I am actually trying to use Suspense with Recoil though so I'm not sure why I'm getting this. Does Next.js not support Suspense or something? It would be kind of a bummer given that I'm not even using SSR outside of dev since I'm running Next Export for a fully static site...

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests