使用babel-plugin-react-css-modules的子组件的className不正确

问题描述

我正在尝试在现有的React项目中使用babel-plugin-react-css-modules。大多数组件都可以正常工作,但是将样式传递给子组件存在问题。

我有一些这样的父组件:

SearchBlock / index.js

import "./style.scss"
import { SettingsIcon } from "../../Icons"
...
<div styleName='SearchBlock'>
   <SettingsIcon size='17' color='#2991F5' />
</div>

SearcBlock / style.scss

.SearchBlock {
  ...

  .SettingsIcon {
     margin-right: 7px;
  }
...
    }

像这样的子组件

SettingsIcon / index.js

const SettingsIcon = (props) => {
...
    return (
      <svg
        width={size}
        height={size}
        viewBox='0 0 24 24'
        fill='none'
        xmlns='...'
        className='SettingsIcon'
      >
...

因此图标在不同的组件中具有适当的样式。

我在生成的CSS文件中得到什么:

.src-components-Search-SearchBlock-___style__SearchBlock___2MeUy .src-components-Search-SearchBlock-___style__SettingsIcon___3SWQh {
        margin-right: 7px; }

似乎正确。但是,子元素的呈现方式如下:

<svg ... class="SettingsIcon"><</svg>

代替

<svg ... class="src-components-Search-SearchBlock-___style__SettingsIcon___3SWQh"><</svg>

我不能在settingsIcon中使用 styleName ,因为Webpack会在不导入至少一个样式表的情况下引发错误

有什么办法可以解决这个问题?


我的配置

webpack.common.js

...
    test: /\.s?css$/,use: [
                    {
                      loader: 'style-loader',},{
                      loader: 'css-loader',options: {
                        modules: {
                          mode: 'local',localIdentName: isProd
                          ? '[hash:base64]'
                          : "[path]___[name]__[local]___[hash:base64:5]",sourceMap: true,importLoaders: 1,onlyLocals: false,{
                      loader: 'postcss-loader',options: {
                        sourceMap: true,{
                      loader: 'sass-loader',],...

babel.config.js

const isProd = process.env.NODE_ENV === 'production';

function createReactCssModulesPlugin() {
  return [
    "react-css-modules",{
      filetypes: {
        ".scss": {
          Syntax: "postcss-scss",plugins: [
            "postcss-import-sync2",[
              "postcss-nested",{
                bubble: ["@include"],preserveEmpty: true,generateScopedname: isProd
        ? '[hash:base64]'
        : "[path]___[name]__[local]___[hash:base64:5]",webpackHotModuleReloading: isProd ? false : true,exclude: "node_modules",handleMissingStyleName: isProd ? "throw" : "warn",autoResolveMultipleImports: true,];
}

module.exports = function (api) {
  api.cache(true)
  return {
    plugins: ["@babel/transform-react-jsx",createReactCssModulesPlugin()],};
};

解决方法

8 个月过去了,您现在可能已经知道答案了,但我还是要发布我的答案。

SearchBlock/style.scss

.SearchBlock {

  .SettingsIcon {
    margin-right: 7px;
  }
}

SettingsIcon/index.js

const SettingsIcon = (props) => {
  return (
    <svg
      ...
      className='SettingsIcon'
    >

这将不起作用,因为您的类 .SettingsIcon 位于 SearchBlock/index.js 中组件的本地范围

您可以像这样在其中设置 SettingsIcon/index.js 的样式:

SettingsIcon/index.js

import "./style.scss" // style for SettingsIcon

const SettingsIcon = (props) => {
  return (
    <svg
      ...
      styleName='SettingsIcon'
    >
  )
}

或者像这样将类作为道具传递:

SearchBlock/index.js

import style from "./style.scss"
import { SettingsIcon } from "../../Icons"

<div styleName='SearchBlock'>
 <SettingsIcon size='17' color='#2991F5' extClasses={ style.SettingsIcon }/>
</div>

SettingsIcon/style.scss

.SearchBlock { ... }

.SettingsIcon {
   margin-right: 7px;
}

SettingsIcon/index.js

import "./style.scss" // style for SettingsIcon

const SettingsIcon = (props) => {
  return (
    <svg
    ...
    styleName={ props.extClasses }
    >
  )
}