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

Storybook中Dialog组件渲染函数报错:缺失args属性

解决Storybook中Story强制要求包含args属性的问题

问题背景

原本Dialog组件的Story代码为:

const meta: Meta<typeof Dialog> = {
  component: Dialog,
  title: "Feedback/Dialog/Dialog",
}

export default meta

type Story = StoryObj<typeof Dialog>

后续修改为使用satisfies关键字的结构:

const meta = {
  component: Dialog,
  title: "Feedback/Dialog/Dialog",
} satisfies Meta<typeof Dialog>

export default meta

type Story = StoryObj<typeof meta>

修改后,使用自定义render函数的Story开始报错,提示必须包含args属性,报错信息如下:

Property 'args' is missing in type '{ render: () => JSX.Element; }' but required in type '{ args: { "aria-describedby"?: string | undefined; "aria-labelledby"?: string | undefined; children?: ReactNode; classes?: Partial | undefined; ... 291 more ...; inlist?: any; }; }'.

完整报错代码:

import { Meta, StoryObj } from "@storybook/react"
import { Box } from "@mui/material"
import { FC, useState } from "react"
import { Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from "components/Dialog"
import { Button } from "components/Button"
import { Typography } from "components/Typography"

const meta = {
  component: Dialog,
  title: "Feedback/Dialog/Dialog",
} satisfies Meta<typeof Dialog>

export default meta

type Story = StoryObj<typeof meta>

type DialogWrapperComponentProps = {
  title?: boolean
  actions?: boolean
}

const DialogWrapperComponent: FC<DialogWrapperComponentProps> = ({ title = false, actions = false }) => {
  const [isModalOpen, setIsModalOpen] = useState(false)

  const handleChange = () => {
    setIsModalOpen(!isModalOpen)
  }

  return (
    <Box>
      <Box style={{ textAlign: "center" }}>
        <Button variant="contained" onClick={handleChange}>
          Открыть модальное окно
        </Button>
      </Box>
      <Dialog open={isModalOpen} onClose={handleChange}>
        {title && <DialogTitle>Фильтр</DialogTitle>}
        <DialogContent sx={{ paddingTop: title ? "0" : "64px" }}>
          <DialogContentText>Lorem ipsum</DialogContentText>
          <Box style={{ width: "376px", height: "200px", backgroundColor: "red", color: "white" }}>content</Box>
          <Box style={{ width: "376px", height: "200px", backgroundColor: "red", color: "white" }}>content</Box>
        </DialogContent>
        {actions && (
          <DialogActions>
            <Button sx={{ width: "180px", borderWidth: "1px", borderStyle: "solid", borderColor: "neutral.800" }} disabled>
              <Typography variant="titleSmall">Сбросить</Typography>
            </Button>
            <Button sx={{ width: "180px" }} variant="contained">
              <Typography variant="titleSmall">Применить</Typography>
            </Button>
          </DialogActions>
        )}
      </Dialog>
    </Box>
  )
}

export const Default: Story = {
  render: () => <DialogWrapperComponent title actions />,
}

export const WithoutActions: Story = {
  render: () => <DialogWrapperComponent title />,
}

export const WithoutTitle: Story = {
  render: () => <DialogWrapperComponent actions />,
}

export const WithoutActionsAndTitle: Story = {
  render: () => <DialogWrapperComponent />,
}

原因分析

问题出在type Story = StoryObj<typeof meta>这一行:当使用StoryObj<typeof meta>时,TypeScript会根据meta中指定的component(即Dialog组件),强制要求所有Story必须包含该组件对应的args属性,即便你使用自定义render函数完全控制了组件渲染流程。

而原写法StoryObj<typeof Dialog>虽然也关联了Dialog组件,但Storybook的类型系统允许在提供render函数时忽略args属性。

解决方案

有三种便捷的解决方式:

方法一:恢复Story类型关联原组件

保留satisfies的meta写法,同时将Story类型改回关联typeof Dialog:

const meta = {
  component: Dialog,
  title: "Feedback/Dialog/Dialog",
} satisfies Meta<typeof Dialog>

export default meta

// 改为关联Dialog组件而非meta
type Story = StoryObj<typeof Dialog>

这种方式既保留了satisfies带来的类型校验能力,又不会强制要求Story必须包含args属性。

方法二:给每个Story添加空args属性

如果不想修改Story类型,可以直接给每个Story添加空的args对象:

export const Default: Story = {
  render: () => <DialogWrapperComponent title actions />,
  args: {},
}

export const WithoutActions: Story = {
  render: () => <DialogWrapperComponent title />,
  args: {},
}
// 其余Story同理添加空args

方法三:在meta中定义默认空args

在meta里添加默认的空args,所有子Story会自动继承这个配置,无需单独添加:

const meta = {
  component: Dialog,
  title: "Feedback/Dialog/Dialog",
  args: {}, // 添加默认空args
} satisfies Meta<typeof Dialog>

export default meta

type Story = StoryObj<typeof meta>

内容的提问来源于stack exchange,提问作者Alice Alikaeva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:52:52