静态服务时,来自不同组件的 React + Material-UI 样式类会发生冲突

And*_*rtz 5 reactjs material-ui jss

问题:重新渲染组件时,应用于由 Material-UI/JSS 生成的类名的样式会错误地更改。

设置:我正在提供一个create-react-app使用 Material-UI jss 样式和 Rails 后端的 React 应用程序(使用 构建)。我不确定 Rails 部分的相关性,因为当我build/index.html直接在本地机器上打开文件时会发生同样的事情——Rails 后端处理根请求以提供静态客户端文件,如此处所示。在任何一种情况下,静态构建都是使用 来创建的npm run build,它运行react-scripts build(从create-react-app)。

问题示例:我有一个<img>给定的元素className: {classes.logo}。构建后,classes.logois "jss3",它采用以下正确的 CSS:

.jss3 {
    height: 50px;
    position: relative;
    // [...more]
}
Run Code Online (Sandbox Code Playgroud)

这看起来像这样 -<img>组件位于应用程序标题的左上角。

在此处输入图片说明

我“继续作为客人”,并呈现新组件。但是请注意徽标图像,它现在具有新样式:

在此处输入图片说明

发生了什么?该<img>组件现在显示以下样式:

.jss3 {
    height: 2em;
    padding: 7px;
    overflow: scroll;
    position: relative;
}
Run Code Online (Sandbox Code Playgroud)

这个 css 来自不同组件的完全不同的样式对象:

// FileEntry.js

  fileEntry: {
    position: 'relative',
    padding: '7px',
    height: '2em',
    overflow: 'scroll',
  },
Run Code Online (Sandbox Code Playgroud)

从日志中,我确定classes.logoinAppHeader.jsclasses.fileEntryfromFileList.js都被命名为"jss3"。这就解释了为什么样式发生了变化——<FileEntry呈现了一个新组件 ( ) 并覆盖了"jss3"类样式。

所以目前的根本问题是:为什么这两个样式元素的名称相互冲突"jss3"?如何使用静态前端应用程序避免这种情况?(当我按照上面博客文章中的说明部署到 heroku 时,也会出现这个问题。)我希望得到一个仍然允许我从一个正在运行的实例同时托管客户端和后端的答案,就像我在这里做的那样,但如果另一个部署设置是最佳答案,那么我很想了解如何 + 为什么。

And*_*rtz 7

该问题与使用两个不同版本的类名生成器有关。有很多方法可以做到这一点;就我而言,当我重构类组件以使用钩子时,我将旧版本material-ui/core/styles#withStyles与新版本混合在一起material-ui/styles#makeStyles。通过删除旧的使用core/styles#withStyles,我解决了这个问题。

发生的情况是两个样式类名生成器互不了解,并使用简单的索引(例如jss3)创建类名。至少,他们在生产构建中这样做,似乎在开发构建中使用了更冗长的基于组件名称的类名,这解释了为什么我只在静态托管时看到它。

由于FileEntry组件直到登录时才被渲染jss3,因此第二个类名生成器直到登录操作之后才会生成类名,此时jss3类被赋予更新的样式,并且浏览器将其应用于现有jss3元素去做。

一些解决方案涉及强制两者使用相同的 Jss 提供程序,但首先不使用类名生成器的独立调用是一个更彻底且支持良好的解决方案。

类似的问题记录在这里: