Next.js: SSR breaks with Material UI && Styled Components

Created on 9 Aug 2019  路  10Comments  路  Source: vercel/next.js

Bug report

Describe the bug

Material UI has FOUC when used with Styled Components beta v5.0.8

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Edit your document.js to
import { ServerStyleSheet } from 'styled-components'
import { ServerStyleSheets } from '@material-ui/styles'
...
  static async getInitialProps(ctx: DocumentContext) {
    const sheets = new ServerStyleSheets()
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage
    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props => ({
            ...sheets.collect(<App {...props} />),
            ...sheet.collectStyles(<App {...props} />)
          })
        })
      const initialProps = await Document.getInitialProps(ctx)
      return {
        ...initialProps,
        styles: (
          <Fragment key="styles">
            {initialProps.styles}
            {sheets.getStyleElement()}
            {sheet.getStyleElement()}
          </ Fragment>
        )
      }
    } finally {
      sheet.seal()
    }
  }
  1. Material UI has FOUC, while styled components works.

If possible can an Example for Next & Material UI & Styled Components be added? These three are used together frequently, but docs do not help.

  "dependencies": {
    "@material-ui/core": "4.3.1",
    "@material-ui/styles": "4.3.0",
    "next": "9.0.3",
    "styled-components": "^5.0.0-beta.8",
  }

Styled Components 5 is coming through soon. I dont think this bug is related to v5 beta though.
```

Most helpful comment

That code looks wrong, you're rendering twice for no good reason 馃

Something like this should work:

ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props => styledComponentsSheet.collectStyles(materialSheets.collect(<App {...props} />))
        })

All 10 comments

@oliviertassinari I followed your starter, but couldn't make it work.

@MarchWorks I tried to follow your guidelines in https://github.com/MarchWorks/nextjs-with-material-ui-and-styled-components but it doesn't seem to work anymore? I also remember trying out your repo, but it had FOUC too.

@Astrantia yes I just solved the problem I will push after 5min

@Astrantia try now

@MarchWorks Your new solution works! Thank you so much for it. Should we close this issue though? Official maintenance might be better, considering that both Material UI and Styled Components are used together very frequently. Material UI is going to adopt Styled Components internally too, so I think this deserves an official example.

Better to ask @timneutkens

@MarchWorks @timneutkens There's currently an issue with the existing solution that @MarchWorks kindly provided. The issue is (node:17652) UnhandledPromiseRejectionWarning: TypeError: Converting circular structure to JSON which might be because of

      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props => materialSheets.collect(<App {...props} />)
        })
      const initialProps = await Document.getInitialProps(ctx)

      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props => styledComponentsSheet.collectStyles(<App {...props} />)
        })
      const initialPropsSec = await Document.getInitialProps(ctx)

      return {
        ...initialProps,
        ...initialPropsSec,

spreading the same initial props in return

That code looks wrong, you're rendering twice for no good reason 馃

Something like this should work:

ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props => styledComponentsSheet.collectStyles(materialSheets.collect(<App {...props} />))
        })

+1 for @timneutkens approach. I think that styled-components is becoming the defacto standard for styling react components. Hopefully, Material-UI will rely on it. In the meantime, does anyone want to contribute instructions for it in our next example? We could add a paragraph about it. At least, it's how we handle the issue with Gatsby.

Just wanted to chime in: I'm working on a NextJS app that uses Grommet, which relies on Styled-Components. I tried this example and it worked for me. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

havefive picture havefive  路  3Comments

formula349 picture formula349  路  3Comments

kenji4569 picture kenji4569  路  3Comments

rauchg picture rauchg  路  3Comments

flybayer picture flybayer  路  3Comments