You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

生产环境Storybook中Material-UI组件代码显示WithStyles而非组件名

问题

我基于Material-UI (v4)组件用Storybook构建设计系统文档,执行生产构建命令:

$ npm run build-storybook
$ npx http-server storybook-static -o

之后,代码块里显示的是WithStyles而非组件真实名称。比如预期显示:

<Button
  color="default"
  onClick={() => {}}
  size="medium"
  variant="contained"
>
  Hello World
</Button>

实际显示成了:

<WithStyles
  color="default"
  onClick={function noRefCheck(){}}
  size="medium"
  variant="contained"
>
  Hello World
</WithStyles>

在Storybook Discord咨询后得到回复:

Storybook uses react-element-to-jsx-string to generate the source blocks, and that library relies on element's displayNames. It looks like you're using MUI, which does not assign displayName in production environments.

但不确定具体解决方法,想问有没有办法让Storybook生产构建时正确生成Material-UI组件的代码块?

解决方法

1. 手动为MUI组件添加displayName

在导入MUI组件的位置,手动为组件设置displayName:

import { Button } from '@material-ui/core';

Button.displayName = 'Button';

如果是自己封装的MUI组件,在导出前设置:

const CustomButton = withStyles(styles)(Button);
CustomButton.displayName = 'CustomButton';

export default CustomButton;

2. 让Storybook生产构建使用MUI开发版本

修改Storybook的Webpack配置,在生产构建时加载MUI未压缩的开发版本(保留displayName)。在.storybook/main.js中添加:

module.exports = {
  webpackFinal: async (config) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      '@material-ui/core': '@material-ui/core/es',
    };
    return config;
  },
};

3. 自定义react-element-to-jsx-string的转换规则

覆盖Storybook默认的代码生成逻辑,手动映射WithStyles包装的组件到真实名称。在.storybook/preview.js中添加:

import { addDecorator } from '@storybook/react';
import reactElementToJSXString from 'react-element-to-jsx-string';
import { Source } from '@storybook/addon-docs';

addDecorator((storyFn) => {
  const element = storyFn();
  const customJSX = reactElementToJSXString(element, {
    displayName: (elem) => {
      // 针对WithStyles包装的组件,手动返回对应名称
      if (elem.type.displayName?.startsWith('WithStyles')) {
        // 可根据组件特征判断,比如这里假设是Button
        return 'Button';
        // 多组件场景可扩展判断逻辑,比如从组件props或内部结构区分
      }
      return elem.type.displayName || elem.type.name || 'Component';
    },
  });
  // 结合Source组件展示自定义生成的JSX代码
  return <Source code={customJSX} />;
});

4. 手动指定文档中的代码示例

如果使用@storybook/addon-docs,可以在Story中直接手动编写代码示例,不依赖自动生成:

import { Button } from '@material-ui/core';
import { Source } from '@storybook/addon-docs';

export default {
  title: 'Components/Button',
  component: Button,
};

export const Default = () => <Button>Hello World</Button>;
Default.parameters = {
  docs: {
    source: {
      code: `<Button
  color="default"
  onClick={() => {}}
  size="medium"
  variant="contained"
>
  Hello World
</Button>`,
    },
  },
};

内容的提问来源于stack exchange,提问作者Nicholas Pappas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 13:50:26