如何在Storybook的args中添加HTML标签或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;
报错信息

解决方案
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
相关产品推荐
相关产品推荐

