Issue: styles applied to class names generated by Material-UI / JSS are incorrectly changing when components are re-rendered.
Setup: I'm serving a React app (built with create-react-app
) that uses Material-UI jss styling and a Rails back end. I'm not sure how relevant the Rails part is since the same thing happens when I open the build/index.html
file directly on my local machine -- the Rails back end handles the root request to serve the static client files as presented here. In either case, the static build is created using npm run build
, which runs react-scripts build
(from create-react-app
).
Example of the issue: I have an <img>
element which is given className: {classes.logo}
. When built, classes.logo
is "jss3"
, which takes on the following correct CSS:
.jss3 {
height: 50px;
position: relative;
// [...more]
}
This looks like this -- the <img>
component is at the top left in the app header.
I "continue as guest", and new components are rendered. But notice the logo image, which now has new styling:
What happened? The <img>
component now shows the following styling:
.jss3 {
height: 2em;
padding: 7px;
overflow: scroll;
position: relative;
}
This css comes from an entirely different style object from a different component:
// FileEntry.js
fileEntry: {
position: 'relative',
padding: '7px',
height: '2em',
overflow: 'scroll',
},
From logs, I've determined that both classes.logo
in AppHeader.js
and classes.fileEntry
from FileList.js
are given the name "jss3"
. So that explains why the styles changed -- a new component (<FileEntry
) was rendered and it overwrote the "jss3"
class styles.
So the root question at the moment is: why are both style elements given the conflicting name "jss3"
? How can I avoid this with a static front-end app? (The issue also occurs when I follow the instructions from the blog post above to deploy to heroku.) I'd love an answer that still allowed me to host both client and back-end from a single running instance as I'm doing here, but if another deployment setup is the best answer then I'd love to learn how + why.
The issue is related to using two different versions of a class name generator. Many ways to do this; in my case I was mixing an older version of material-ui/core/styles#withStyles
with a newer material-ui/styles#makeStyles
as I was refactoring class components to use hooks. By removing usage of the older core/styles#withStyles
, I fixed the issue.
What happens is the two style classname generators don't know about each other, and create class names with simple indexes (e.g. jss3
). At least, they do this for production builds, it seems there use more verbose component-name-based class names in dev builds, which explains why I was only seeing it when hosting statically.
Since the FileEntry
component was not rendered until login, the jss3
class name was not generated by the second class name generator until after the login action, at which point the jss3
class was given updated styling, and the browser applied it to the existing jss3
elements as it is meant to do.
Some workaround solutions involved forcing both to use the same Jss Provider, but not using independent invocations of class name generators in the first place was a more thorough and well-supported solution.
Similar issues are documented here:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With