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

Server side rendering with Express - warning on the client checksum & Styling #4466

Closed
sabha opened this issue Jun 10, 2016 · 7 comments
Closed
Labels
support: question Community support but can be turned into an improvement

Comments

@sabha
Copy link

sabha commented Jun 10, 2016

Problem description

I could see the below warning even after passing the userAgent while rendering on the server side. Please assist me on this , if I am doing anything wrong. On the client side React is trying to reuse markup(component) , since checksum is invalid so it is throwing the warning. I could see the issue is due to Isomorphic styling and node is not able to compile the CSS (I may be wrong).

Code
https://github.com/sabha/React-Redux-Router-MaterialUI-ServerSideRendering

Server Side Rendering

global.navigator = {
          userAgent: req.headers['user-agent']
        };
      const muiTheme = getMuiTheme({userAgent: req.headers['user-agent']});  
      // hey we made it!
      const appHtml = renderToString(
        <MuiThemeProvider muiTheme={muiTheme}>
          <Provider store={store}>
              <RouterContext {...props}/>
          </Provider>
        </MuiThemeProvider>
          )

Client Side Render

import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

render(  
    <MuiThemeProvider muiTheme={getMuiTheme()}>
        <Provider store={store}>
            <Router routes={LoginRoutes} history={browserHistory}/>
        </Provider>
    </MuiThemeProvider>,
  document.getElementById('app')
)

MUI Component

'warning.js:44Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) 0;text-align:center;mui-prepared:;-webki
(server) 0;text-align:center;-webkit-user-select:'

@sabha sabha changed the title Server side rendering with Express - data-react-checksum - Styling Server side rendering with Express - warning on the client checksum & Styling Jun 10, 2016
@sabha
Copy link
Author

sabha commented Jun 11, 2016

Is it good practice to go with this warning and fix it later or I should build the app with client side rendering and later make the server side rendering . .

@OshotOkill
Copy link

OshotOkill commented Jun 15, 2016

I've met this problem before and dealt with it for a long period. I don't use react-router so I've no idea this would help you. The solution is simple, just passing navigator.userAgent value to your custom theme in client side AGAIN, it's like:

 <MuiThemeProvider muiTheme={getMuiTheme({userAgent: navigator.userAgent)}>
   <Provider store={store}>
     ... 
   </Provider>
</MuiThemeProvider>

@sabha
Copy link
Author

sabha commented Jun 20, 2016

@OshotOkill Still the same warning.

@nnnnathann
Copy link

I had this problem, I was able to get around it by monkeypatching the prepareStyles method to ignore muiPrepared when passing style props onto react.

var theme = getMuiTheme({}, { userAgent: ... });
var original = theme.prepareStyles;
theme.prepareStyles = function(style) {
    var out = style.muiPrepared ? style : original(style);
    if (out && out.muiPrepared) {
        delete out.muiPrepared;
    }
    return out;
};

Hope that helps!

@mpontikes mpontikes mentioned this issue Aug 5, 2016
13 tasks
@catamphetamine
Copy link

catamphetamine commented Aug 11, 2016

@OshotOkill So how do you get the code working isomorphically?
It can be request.headers['user-agent'] on the server side and navigator.userAgent on the client side, but the global navigator variable should not be set on the server side.

@catamphetamine
Copy link

catamphetamine commented Aug 11, 2016

Well, for those who are googling for this issue: I managed to sort out the navigator issue by storing navigator (taken from request.headers['user-agent']) inside Redux store (and putting it there on the server side, therefore client-side navigator.userAgent is not used at all).

@connect(model => ({ navigator: model.navigator }))
export default class Form extends Component
{
    getChildContext()
    {
        return {
            muiTheme: getMuiTheme({ userAgent: this.props.navigator.userAgent })
        }
    }
}

// `navigator` reducer must also be created otherwise `navigator` will be `undefined`

It fixed the autoprefixer "React attempted to reuse markup" warning, but here's the new one:

Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) aitDialog-undefined-8741" style="-webkit
(server) aitDialog-undefined-3418" style="-webkit
Server-side React render was discarded. Make sure that your initial render does not contain any client-side code.

The cause of the error is this weird autogenerated id:
id="undefined-PortraitDialog-undefined-8741"
Which has, apart from the weird undefined parts, that randomly generated number in the end, which is different every time a render happens therefore discarding previously rendered React markup.

This issue is unresolved and is described in #3757
Specifying a manually set id on a <DatePicker/> seems to have worked around this issue.

@sabha
Copy link
Author

sabha commented Sep 15, 2016

Solved the issue but setting process.env for the client side.

 plugins: [
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
            }
        }),
    ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
support: question Community support but can be turned into an improvement
Projects
None yet
Development

No branches or pull requests

5 participants