【问题标题】:Incorrect className of child component using babel-plugin-react-css-modules使用 babel-plugin-react-css-modules 的子组件的类名不正确
【发布时间】:2020-12-07 22:51:16
【问题描述】:

我正在尝试在现有的 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',
                      options: {
                        sourceMap: true,
                      },
                    },
                  ],
            },
...

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()],
  };
};

【问题讨论】:

    标签: reactjs webpack babel-plugin-react-css-modules


    【解决方案1】:

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

    SearchBlock/style.scss

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

    SettingsIcon/index.js

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

    这将不起作用,因为您的类 .SettingsIconSearchBlock/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 }
        >
      )
    }
    

    【讨论】:

      猜你喜欢
      • 2017-09-04
      • 2019-04-22
      • 2021-07-31
      • 2017-05-21
      • 2020-05-01
      • 2018-05-20
      • 1970-01-01
      • 1970-01-01
      • 2023-01-12
      相关资源
      最近更新 更多