Material-ui: react SSR className mismatch in production mode

Created on 11 Mar 2019  ·  36Comments  ·  Source: mui-org/material-ui


In the development environment, ssr runs normally. When running in the production environment, the page is opened for the first time. The style corresponding to the class name exists, but there is no defined css.

  • [ ] This is not a v0.x issue.
  • [ ] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior 🤔


image

Current Behavior 😯


image

Steps to Reproduce 🕹


The development environment is normal, the production environment is rendered incorrectly for the first time, the console does not have any error or warning, and all configurations are configured according to the document. It puzzled me for two days without solving it. please help me

Context 🔦

Your Environment 🌎

| Tech | Version |
|--------------|---------|
| Material-UI | v3.9.2 |
| React | v16.8.3 |
| Browser | chrome |
| Jss | v9.8.7 |
| jss-preset-default | v10.0.0-alpha.7 |

styles

Most helpful comment

Oh, by the way @oliviertassinari, I found a way to solve my bug, and maybe this issue I don't know. I had to specify an extra prop to my styles in order to put injected css at the right position:

const useStyles = makeStyles(
  theme => ({
    drawerBase: {
      width: 275,
      flexShrink: 0
    }, // etc...
  }),
  { name: 'HookGlobalStyles', index: 2 }
)

All 36 comments

Do you have a minimal reproducible example? Looking at the ssr example might help you https://github.com/mui-org/material-ui/tree/next/examples/ssr

@joshwooding I have the same configuration as the documentation you provided. I still have this problem, and it only appears in the production environment. The development environment is fine. Should I upload the project to github and attach the link address?

@chnliquan Yes please :)

@joshwooding https://github.com/chnliquan/react-cnode
use the production mode wil accur this issue

npm install
npm run build
npm start
open http://localhost:9000

@chnliquan I have tried your reproduction. It's working great on my end.

@oliviertassinari Are you sure you are in a production environment? First use npm run build to package, then npm start to start the service, open http://localhost:9000. In the first rendering, the className of the list page will not match (it lead the list item user avatar becomes very large), and the tab will be restored. I just executed it again, the same problem.

@material-ui/core v3.9.2
@material-ui/core v3.0.2
@jss v9.8.7
@jss-preset-default-10.0.0-alpha.7

Facing similar JSS issues with SSR: One or more classnames share common styles.

Please check code here: https://github.com/atulmy/hire-smart (open source project)
And live website here: https://hiresmart.app/ (try to repeatedly move between routes)

Check following screenshot:
Screenshot 2019-03-13 at 3 49 48 AM

Same issue here, looking for help

You should find a solution in https://next.material-ui.com/guides/server-rendering/#troubleshooting. However, this issue is soo common, I'm going to change some architectural choices.

I don't know if it's the same issue @oliviertassinari but I'm not the only one with unpredictable JSS injection.

On hiresmart, we can see that styles are messed up (like my website, not published yet):
image

On my side, it's when I'm mixing old school Theme with Hooks:

import { createMuiTheme } from '@material-ui/core/styles'
import { makeStyles } from '@material-ui/styles'
const theme = createMuiTheme({
  overrides: {
    // lots of overrides here
  }
})
const styles = theme => ({ ... })
const useStyles = makeStyles(...)
export { theme, styles, useStyles }
 <ThemeProvider theme={theme}>
  <Router>
    ...
  </Router>
</ThemeProvider>
class Request extends Component {

}
export default withStyles(styles, { withTheme: true })(Request)

@MBach Are you doing server-side rendering?

I'm not, it's just a react-scripts build but the issue described here is very similar to what I encounter.

@MBach Interesting, how can we produce it?

Actually I'm creating a repository where I'm removing everything "not critical" but I have some other deadlines until next week ...

I experience this (or related) issue on the nextjs-next example, whereas before 4.0.0-alpha.3 everything was fine.
I don't see a console error about mismatched classnames but I do see the server render without styles then styles come in when the client renders.

I saw this from a fully clean checkout of the example.

You should find a solution in https://next.material-ui.com/guides/server-rendering/#troubleshooting. However, this issue is soo common, I'm going to change some architectural choices.

I have checked it many times, all the steps are the same as described in the documentation, or there is still this problem 😫. https://next.material-ui.com/guides/server-rendering/#troubleshooting

@chnliquan I have tried your reproduction. It's working great on my end.

You are running normally because the server failed to get the initial data, and then the client retrieved the request and re-rendered it. I also reappear on my colleague's machine, but if the initial data is taken, the rendering will appear className mismatch

I'm also getting this warning:
Warning: Prop className did not match. Server: "MuiSvgIcon-root-1481" Client: "MuiSvgIcon-root-61"

We are introducing a server-side rendering API: #15030. I hope this new API will leave very little room for error.

Oh, by the way @oliviertassinari, I found a way to solve my bug, and maybe this issue I don't know. I had to specify an extra prop to my styles in order to put injected css at the right position:

const useStyles = makeStyles(
  theme => ({
    drawerBase: {
      width: 275,
      flexShrink: 0
    }, // etc...
  }),
  { name: 'HookGlobalStyles', index: 2 }
)

@oliviertassinari I want know how did you confirm the classNames of client are same to server and ensure them can't mismatch

@0-Captain I'm not sure to follow your question. We are documenting the most common source of problems: https://material-ui.com/guides/server-rendering/#troubleshooting.

@oliviertassinari It seems that the client's generateClassName have no relation with server's generateClassName, so how to ensure it work rightly?I have looked the solution and correct my code, but no effect. The className still mismatch when first render。

@0-Captain The problem is handled by #15030. Do you think that you could move to v4.0.0-alpha.6 when it's released this weekend?

@oliviertassinari Ok, thank you

The latest ssr-next example does not work when running production. like this
<style data-jss="" data-meta="makeStyles"> .jss1 { text-align: center; padding-top: 160px; } </style>
<div class="App-root-1"></div>
Am I doing something wrong? @oliviertassinari

@girlsfamily I have just tried the example. It's working fine.

It's my fault. it's good now

@girlsfamily what was your fix?

@girlsfamily what was your fix?

try the latest ssr example. I missed cross-env NODE_ENV=production before

NODE_ENV=production fixed it here, too. Thanks!

I have this problem, where to do I add NODE_ENV=production in my create-react-app?

Can anyone explain why it NODE_ENV has to be set to production? We are trying to deploy test applications and just ran into this error for two hours before I just tried setting the env var to production instead of testing. I feel like the CSS injection should be agnostic to development environment, no?

@dallen4 As long as the client and the server use the same value for process.env.NODE_ENV, you should be good, it doesn't need to be a specific value but it needs to match.

@chnliquan I have tried your reproduction. It's working great on my end.

You are running normally because the server failed to get the initial data, and then the client retrieved the request and re-rendered it. I also reappear on my colleague's machine, but if the initial data is taken, the rendering will appear className mismatch

I have the same problem as you. How did you solve it? I really need your help. Thank you

Oh, by the way @oliviertassinari, I found a way to solve my bug, and maybe this issue I don't know. I had to specify an extra prop to my styles in order to put injected css at the right position:

const useStyles = makeStyles(
  theme => ({
    drawerBase: {
      width: 275,
      flexShrink: 0
    }, // etc...
  }),
  { name: 'HookGlobalStyles', index: 2 }
)

can't believe but it solved my issue as well! Thanks! :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mattmiddlesworth picture mattmiddlesworth  ·  3Comments

finaiized picture finaiized  ·  3Comments

ryanflorence picture ryanflorence  ·  3Comments

chris-hinds picture chris-hinds  ·  3Comments

ghost picture ghost  ·  3Comments