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')
)
'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:'
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 . .
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>
@OshotOkill Still the same warning.
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!
@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.
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 https://github.com/callemall/material-ui/issues/3757
Specifying a manually set id
on a <DatePicker/>
seems to have worked around this issue.
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)
}
}),
]
Most helpful comment
Solved the issue but setting
process.env
for the client side.