无法在 Storybook 中按类名设置我的 React 组件样式

Posted

技术标签:

【中文标题】无法在 Storybook 中按类名设置我的 React 组件样式【英文标题】:Can't style my React Components by Class Name in Storybook 【发布时间】:2019-11-12 09:56:55 【问题描述】:

我无法在 Storybook 中通过类名来设置我的 react 组件的样式!

如果我使用div<h1> 等通用元素,那么我可以设置一些样式。它必须与我的 webpack 配置有关,但我只是不知道是什么。

我的rules.js 被传递到webpack.config.js

rules.js

const  configureBabel  = require('../_babel.config');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');

/**
 * @param themePaths ThemePaths
 * @param selectMode SelectMode
 * @param selectTarget SelectTarget
 * @returns *[]
 */
function rules(themePaths, selectMode, selectTarget) 
    const babelOptions = configureBabel(selectMode, selectTarget);
    const babelEnvDeps = require('webpack-babel-env-deps');
    return [
        
            test: /\.graphql$/,
            exclude: /node_modules/,
            use: [
                
                    loader: 'graphql-tag/loader',
                ,
            ],
        ,
        
            include: [
                path.resolve(__dirname, '..', 'server'),
                path.resolve(__dirname, '..', 'runtime'),
                themePaths.src,
                themePaths.generated,
                path.resolve(__dirname, '..', '..', 'swagger'),
                path.resolve(__dirname, '..', 'node_modules', 'debug'),
                babelEnvDeps.include(),
            ],
            // exclude: [/node_modules/],
            test: /\.(ts|tsx|mjs|js|svg|graphql)$/,
            use: [
                
                    loader: 'babel-loader',
                    options: babelOptions,
                ,
            ],
        ,
        
            test: [/\.scss$/],
            use: [
                selectMode( development: 'style-loader' ),
                selectMode( production: MiniCssExtractPlugin.loader ),
                
                    loader: 'css-loader',
                    options: 
                        importLoaders: 1,
                        localIdentName: '[name]-[local]-[hash:base64:3]',
                        modules: true,
                    ,
                ,
                
                    loader: 'sass-loader',
                    options: 
                        data: `
                        @import "_vars";
                        @import "_mixins";
                        @import "_normalize";
                        @import "_reset";
                        `,
                        includePaths: ['src/scss'],
                    ,
                ,
                
                    loader: 'postcss-loader',
                    options: 
                        ident: 'postcss',
                        plugins: [require('autoprefixer')()],
                    ,
                ,
                'resolve-url-loader',
            ].filter(Boolean),
        ,
        
            test: /\.(jpe?g|png|svg|gif)$/,
            use: [
                
                    loader: 'file-loader',
                    options: ,
                ,
            ],
        ,
        
            test: /\.(woff2?)$/,
            use: [
                
                    loader: 'file-loader',
                    options: 
                        name: '[path][name].[ext]',
                    ,
                ,
            ],
        ,
    ];


module.exports.rules = rules;

我的webpack.config.js

const  resolve  = require('path');

module.exports = (baseConfig, env, defaultConfig) => 
    const rulesFn = require('../.webpack/rules').rules;
    const rules = rulesFn(
        
            outputLegacy: '',
            generated: '',
            output: '',
            src: '',
        ,
        input => input['development'],
        input => input['modern'],
    );
    delete rules[1].include;
    defaultConfig.module.rules = rules;
    defaultConfig.resolve.extensions = ['.ts', '.tsx', '.js'];
    defaultConfig.resolve.alias = 
        ...(defaultConfig.resolve.alias || ),
        swagger: resolve(__dirname, '..', '..', 'swagger'),
    ;

    return defaultConfig;
;

我的config.ts

import  configure  from "@storybook/react";

const req = require.context('../src/', true, /.stories.tsx$/);

function loadStories() 
    req.keys().forEach((filename) => req(filename))


configure(loadStories, module);

我的 React 组件EateryItem.tsx

import React from "react";
import "./EateryItem.scss";

export const EateryItem: React.SFC<any> = props => 
  return (
    <div className="Eatery" key=props.id>
      <h3 className="name">props.name</h3>
      <p className="address">props.address</p>
      <p className="type">props.foodType</p>
    </div>
  );
;

我的EateryItem.scss 似乎可以通过类名来设置这些样式

.Eatery 
    border: 5px dashed $color-primary;
    margin: $base-spacing;


.name 
    background: red;

不知道为什么我不能设置这些类名的样式?

【问题讨论】:

【参考方案1】:

所以我在从我的故事书 webpack 检查注入的 .js 文件中的类名后最终意识到它正在对类名进行哈希处理。

我进入我的 rules.js 并通过将其设置为 false 来关闭 css 模块。

loader: 'css-loader',
options: 
  importLoaders: 1,
  localIdentName: '[name]-[local]-[hash:base64:3]',
  modules: false,
,

然后它停止了对classNames 的哈希处理,它开始工作了!

【讨论】:

您的规则文件在哪里?这是你写的吗? 是的,你可以在这里查看我的 repo,它位于一个单独的 .webpack 文件夹中。我已经为每个人提供了这个样板github.com/hghazni/killer-storybook-config 谢谢。最近几天我经历了地狱,但我已经在你的 github 上添加了书签,谢谢。

以上是关于无法在 Storybook 中按类名设置我的 React 组件样式的主要内容,如果未能解决你的问题,请参考以下文章

Selenium在python中按类名查找悬停按钮元素

构建 Angular 库后无法将 SCSS 与 Storybook 一起使用

Vue 3 Storybook:(PrimeVue)组件不显示

无法读取未定义的属性“移动”-Vue/Vuetify/Storybook

@storybook/angular 无法在故事索引上加载 scss 文件

无法在 NextJs + Storybook 中提供静态文件