Storybook组件传参报错:TypeError: data.map is not a function
问题描述
向Storybook关联的组件传递props时,传入的对象无法执行map方法,报错:
TypeError: data.map is not a function
推测传入的不是数组,以下是当前代码,需要修正使props成为可映射的数组:
Works.mocks.ts
import { ImgixImage } from '@/model/storage'; import { IWorks } from './Works'; const base: IWorks = [ { projectID: 1, projectName: 'Project - 1', projectPic: { url: ImgixImage.main_portfolio1, width: 360, height: 480 }, projectDesc: 'Project - 1 || Photo booth fam kinfolk cold-pressed sriracha leggings jianbing microdosing tousled waistcoat.', }, { projectID: 2, projectName: 'Project - 2', projectPic: { url: ImgixImage.main_portfolio2, width: 360, height: 480 }, projectDesc: 'Project - 2 || Photo booth fam kinfolk cold-pressed sriracha leggings jianbing microdosing tousled waistcoat.', }, { projectID: 3, projectName: 'Project - 3', projectPic: { url: 'https://dummyimage.com/720x400', width: 360, height: 480, }, projectDesc: 'Project - 3 || Photo booth fam kinfolk cold-pressed sriracha leggings jianbing microdosing tousled waistcoat.', }, ]; export const mockWorksProps = { base, };
Works.tsx
import Image from 'next/image'; interface project { projectID: number; projectName: string; projectPic: { url: string; width: number; height: number }; projectDesc: string; } export interface IWorks extends Array<project> {} const Works: React.FC<IWorks> = (works: IWorks) => { const data = works; return ( <div className=""> <div className=""> <div className=""> {data.map(({ projectID, projectName, projectPic, projectDesc }) => ( <div key={projectID} className=""> <div className=""> <Image className="" src={projectPic.url} width={projectPic.width} height={projectPic.height} alt="https://dummyimage.com/360x480" /> </div> </div> ))} </div> </div> </div> ); }; export default Works;
Works.stories.tsx
import { ComponentMeta, ComponentStory } from '@storybook/react'; import Works, { IWorks } from './Works'; import { mockWorksProps } from './Works.mocks'; export default { title: 'templates/Works', component: Works, argTypes: {}, } as ComponentMeta<typeof Works>; const Template: ComponentStory<typeof Works> = (args) => <Works {...args} />; export const Base = Template.bind({}); Base.args = { ...mockWorksProps.base, } as IWorks;
修正方案
问题核心:你把数组类型直接当作组件的props类型,但React组件的props本质是对象,直接传递数组并展开会把数组索引转为props的key,导致组件接收的是对象而非数组,无法调用map。
1. 重构Works.tsx的props定义
改为通过对象属性传递数组:
import Image from 'next/image'; // 统一命名为大写开头的接口规范 interface Project { projectID: number; projectName: string; projectPic: { url: string; width: number; height: number }; projectDesc: string; } // 定义组件props类型:包含一个works数组属性 export interface WorksProps { works: Project[]; } const Works: React.FC<WorksProps> = ({ works }) => { return ( <div className=""> <div className=""> <div className=""> {works.map(({ projectID, projectName, projectPic, projectDesc }) => ( <div key={projectID} className=""> <div className=""> <Image className="" src={projectPic.url} width={projectPic.width} height={projectPic.height} alt={projectName} // 替换为有意义的alt文本 /> </div> </div> ))} </div> </div> </div> ); }; export default Works;
2. 调整Works.mocks.ts的类型(可选)
保持类型一致性,将base改为Project[]类型:
import { ImgixImage } from '@/model/storage'; import { Project } from './Works'; const base: Project[] = [ // 原数据内容不变 ]; export const mockWorksProps = { base, };
3. 修改Storybook的传参方式
在故事文件中正确传递包含works属性的props:
import { ComponentMeta, ComponentStory } from '@storybook/react'; import Works, { WorksProps } from './Works'; import { mockWorksProps } from './Works.mocks'; export default { title: 'templates/Works', component: Works, argTypes: {}, } as ComponentMeta<typeof Works>; const Template: ComponentStory<typeof Works> = (args) => <Works {...args} />; export const Base = Template.bind({}); Base.args = { works: mockWorksProps.base, // 直接传递数组作为works属性 } as WorksProps;
内容的提问来源于stack exchange,提问作者BJ GDRX
相关产品推荐
相关产品推荐

