[styles] Server side rendering issues style on client hydratation multiple components
See original GitHub issue- The issue is present in the latest release.
- I have searched the issues of this repository and believe that this is not a duplicate.
Current Behavior 😯
I have two React components that are server rendered on a page. My server renderer js file contains this
const generateClassName = createGenerateClassName({
seed: componentName,
});
const sheets = new ServerStyleSheets({
serverGenerateClassName: generateClassName,
});
const html = ReactDOMServer.renderToString(
sheets.collect(reactElement),
);
I have to use a seed (here the name of the component at hand) so as to avoid class collisions on the server rendered page.
The server rendered page gets displayed correctly.
But when I render my page on the client, the first component gets hydrated correctly, though, the second component does not.
I use this
React.useEffect(() => {
const jssStyles = document.querySelectorAll('.jss-server-side');
if (jssStyles) {
jssStyles.forEach(function(item) {
item.parentNode.removeChild(item);
});
}
}, []);
to remove the style on the client.
And this const generateClassName = createGenerateClassName({ seed: componentName, });
and this <StylesProvider generateClassName={generateClassName}></StylesProvider>
to wrap my component.
For some classes on the second component I have no style at all. Sometimes both seed are present in classes.
Am I doing something wrong? What should I be doing?
Maybe not using seeds would solve the problem? Is there any way to render two components (two differents calls, two differents react trees) without class clashes in the first place on the server?
Thank you for reading, and thank you for the lib!
Tech | Version |
---|---|
Material-UI | v4.9.3 |
Material-UI Styles | v4.9.0 |
React | v16.12.0 |
Browser | Chrome… |
Issue Analytics
- State:
- Created 4 years ago
- Comments:11 (4 by maintainers)
Top GitHub Comments
We had a similar problem for this, and it took a team of three a full week to find all the bugs. The fixes for us were as follows:
NODE_ENV
. When they don’t match,material-ui
does funky thingsproductionPrefix
between the two environments; ensure that the client uses aStylesProvider
withgenerateClassNames
in the options while the server uses anew ServerStyleSheets()
with aserverGenerateClassNames
in the options. This difference in option keys is undocumented, so the maintainers should either update the docs or allowServerStyleSheets
to acceptgenerateClassName
makeStyles
calls, use the second option to name the style and assign an elevation, eg{ name: "MyComponent", elevation: 1 }
. This will help you find style conflicts and avoid classname collisions.Thanks to the maintainers for the excellent package and for all your work. I hope this helps you get to a resolution quicker than we did.
An update, we have now made enough progress with the new
@material-ui/styled-engine
package in v5 to move toward a progressive removal of the@material-ui/styles
package (based on JSS). The current plan:sx
prop +styled()
API). We might for instance, invest in the documentation for using react-jss that has more or less the same API. We could also invest in an adapter to restore the previous API but with emotion, not JSS.withStyles
/makeStyles
API).This was made possible by the awesome work of @mnajdova.