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

如何在Storybook的args中添加HTML标签或React组件/元素?

Storybook中Button组件传入React元素的简化方案

问题描述

在Storybook中使用Button组件时,当前只能通过React.createElement给icon参数传入React元素,直接写HTML标签会报错“无法找到名称{tag}”。后续需要给组件传入表单作为子元素,使用React.createElement会非常繁琐,寻求解决方案。

Button组件类型定义

import React from 'react'
export type ButtonProps = {
  label: string;
  color?: 'primary' | 'secondary' | 'tertiary';
  size?: 'mobile' | 'tablet' | 'desktop';
  handleClick?: () => void;
  fullWidth?: boolean;
  loading?: boolean;
  href?: string;
  icon?: React.ReactNode;
  target?: '_blank' | '_parent';
  disabled?: boolean;
}

现有Storybook代码

import React from 'react';
import { Meta, StoryObj } from "@storybook/react";
import { Button as SampleButton } from "../../components";
import 'antd/dist/reset.css';

const buttonMeta: Meta<typeof SampleButton> = {
  title: "Components/Button",
  tags: ['autodocs'],
  component: SampleButton,
};

export default buttonMeta;

type Story = StoryObj<typeof buttonMeta>;

export const Primary: Story = {
  args: {
    label: "Testing",
    icon: React.createElement('h1', null, 'Icon')
  },
};

Storybook配置(Main.ts)

import type { StorybookConfig } from "@storybook/react-webpack5";
const config: StorybookConfig = {
  stories: ["../src/stories/**/*.mdx", "../src/stories/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/preset-create-react-app",
    "@storybook/addon-interactions",
    '@storybook/addon-docs'
  ],
  framework: {
    name: "@storybook/react-webpack5",
    options: {},
  },
  docs: {
    autodocs: "tag",
  },
  staticDirs: ["..\\public"],
};
export default config;

报错信息

无法找到名称“h1”的报错

解决方案

1. 使用Story的render方法替代args传React元素

Storybook允许在Story中定义render函数,直接使用JSX语法渲染组件,这样可以避免繁琐的React.createElement,同时支持传入复杂的子元素(如表单)。

修改后的示例代码:

export const Primary: Story = {
  render: (args) => (
    <SampleButton {...args} icon={<h1>Icon</h1>}>
      {/* 直接写入表单作为子元素 */}
      <form style={{ padding: '8px' }}>
        <input type="text" placeholder="请输入用户名" style={{ marginRight: '8px' }} />
        <button type="submit">提交</button>
      </form>
    </SampleButton>
  ),
  args: {
    label: "Testing",
  },
};

2. 确保TypeScript配置支持JSX

检查项目根目录的tsconfig.json,确保jsx选项正确配置,避免JSX语法报错:

{
  "compilerOptions": {
    "jsx": "react-jsx" // 或 "react",根据React版本选择
  }
}

3. 复用Template函数(可选)

如果需要多个Story共享基础配置,可以定义Template函数,在不同Story中扩展:

const Template: Story = {
  render: (args) => <SampleButton {...args} />
};

export const WithForm: Story = {
  ...Template,
  render: (args) => (
    <SampleButton {...args} icon={<span>📝</span>}>
      <form>
        <input type="email" placeholder="邮箱" />
        <button type="submit">订阅</button>
      </form>
    </SampleButton>
  ),
  args: {
    label: "带表单按钮",
    color: "primary"
  }
};

原理说明

  • args字段主要用于传递可序列化的简单参数(如字符串、布尔值),直接在args中写JSX会被TypeScript识别为未定义变量,因为不在JSX上下文环境中。
  • render函数提供了完整的JSX上下文,可以直接编写React元素,包括复杂的组件嵌套和子元素,同时还能通过...args复用基础参数配置。

内容的提问来源于stack exchange,提问作者Haseeb Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 16:23:31