BJ GDRX
BJ GDRX

Reputation: 79

Can't map component prop

I am passing props to my component that link to storybook. Problem is object that i pass in is don't map. and it says

"TypeError: data.map is not a function".

So i think my object is not an "array" yet and i tried fix until code look like this.

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;

What is need to fix prop as an "array" ? Help of any kind is much appreciated

Upvotes: 1

Views: 198

Answers (1)

Drew Reese
Drew Reese

Reputation: 202706

React components take a props object as an argument, not direct prop value. In Works you've named the entire props object works. works should instead be a property of the props object.

interface project {
  projectID: number;
  projectName: string;
  projectPic: { url: string; width: number; height: number };
  projectDesc: string;
}

export interface IWorks {
  works: Array<project>;
}

const Works: React.FC<IWorks> = ({ works }: IWorks) => {
  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="https://dummyimage.com/360x480"
                />
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

...

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 = {
  works: mockWorksProps.base, // <-- pass a works prop
} as IWorks;

Upvotes: 1

Related Questions