storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.55k stars 9.29k forks source link

Storybook 6.5: React - Using array of objects as child for component throws error #18269

Open daniel-stoian-lgp opened 2 years ago

daniel-stoian-lgp commented 2 years ago

Describe the bug When using an array of objects as a child for a component, @storybook/react throws the error below: Objects are not valid as a React child (found: object with keys {icon, children, key}). If you meant to render a collection of children, use an array instead But I am using an array :) Here is a screenshot of the array used as a child and the error:

image

To Reproduce

System Environment Info:

System: OS: Windows 10 10.0.19044 CPU: (12) x64 Intel(R) Core(TM) i7-10810U CPU @ 1.10GHz Binaries: Node: 14.19.1 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.18 - ~\AppData\Roaming\npm\yarn.CMD npm: 6.14.16 - C:\Program Files\nodejs\npm.CMD Browsers: Edge: Spartan (44.19041.1266.0), Chromium (101.0.1210.47)

Additional context Issue was not reproduced in storybook 6.3 or 6.4

shilman commented 2 years ago

Do you a have a reproduction repo you can share? If not, can you create one? See how to create a repro. Thank you! 🙏

daniel-stoian-lgp commented 2 years ago

@shilman , here is the demo repo https://github.com/daniel-stoian-lgp/storybook6.5Bug I tried to publish it to chromatic, but it doesn't let me publish it because it finds the same error I described in this issue

EDIT: I also added a branch named storybook6.4.22 for the same app, https://github.com/daniel-stoian-lgp/storybook6.5Bug/compare/storybook6.4.22 The array of objects is rendered

image

PxlBuzzard commented 2 years ago

I can reproduce this issue because I am trying to pass an object as children to a React component (the parent component converts it to more React components). Works fine in 6.4.22, same error as OP in 6.5.6.

export const Basic = () => {
  const obj = {
    type: "Example",
    version: "1.0.0",
  };

  return <ExampleDocument>{obj}</ExampleDocument>;
};
promet99 commented 2 years ago

I can reproduce this issue because I am trying to pass an object as children to a React component (the parent component converts it to more React components). Works fine in 6.4.22, same error as OP in 6.5.6.

export const Basic = () => {
  const obj = {
    type: "Example",
    version: "1.0.0",
  };

  return <ExampleDocument>{obj}</ExampleDocument>;
};

Is it legit to provide object as component's children?

zhangjing28 commented 2 years ago

Same to PxlBuzzard, but mine did not work in 6.4.22 either

daniel-stoian-lgp commented 2 years ago

@shilman , do you have an estimation for the fix of this issue?

zhyd1997 commented 2 years ago

@daniel-stoian-lgp

change children to another word maybe works for you:

https://github.com/daniel-stoian-lgp/storybook6.5Bug/blob/f3597486c1360d2739b5d497643f1b87c5056356/stories/KeyGuide.jsx#L26

because children is a reserved keyword in react-dom: https://github.com/facebook/react/blob/e225fa43ada4f4cf3d3ba4982cdd81bb093eaa46/packages/react-dom/src/shared/DOMProperty.js#L244-L246

daniel-stoian-lgp commented 2 years ago

@zhyd1997 , do you know if this was a breaking change recently? because the setup worked with react-dom 18.0.0 and storybook 6.4.22

zhyd1997 commented 2 years ago

@daniel-stoian-lgp

seems that it is not the change recently:

Screen Shot 2022-07-12 at 18 12 50

and it works now after renaming the props.

btw, do you have a repo setup with sb 6.4.22?

daniel-stoian-lgp commented 2 years ago

@zhyd1997 , it is the same repo, but checkout branch storybook6.4.22. see my previous comment https://github.com/storybookjs/storybook/issues/18269#issuecomment-1132601519

zhyd1997 commented 2 years ago

@daniel-stoian-lgp

the branch init failed when running yarn install.

zhyd1997 commented 2 years ago

and storybook 6.4.22 is only compatible with react 16 or 17:

Screen Shot 2022-07-12 at 18 28 43

you can try it by yourself:

npx create-react-app my-app --template typescript

npm i --save-dev @storybook/react@6.4

ref: how to install older version storybook.

daniel-stoian-lgp commented 2 years ago

@zhyd1997 , i was using npm install --force. react 18 is backwards compatible

zhyd1997 commented 2 years ago

@daniel-stoian-lgp

the error was reported by react, so have you tried it in CRA without storybook?

the component will be used in the real react component finally, so even if it works for specific storybook, it is still not valid in react.

daniel-stoian-lgp commented 2 years ago

@zhyd1997 , yes i used the same data in the component outside storybook with React 17 and React 18 with no problems

zhyd1997 commented 2 years ago

here the children should be react elements like Button.stories.jsx:

Screen Shot 2022-07-12 at 20 51 43

but actually, it is an array:

Screen Shot 2022-07-12 at 20 56 35

as we known, typeof [] === 'object' in Javascript, as the error showed.

zhyd1997 commented 2 years ago

According to the error call stack, it's caused by this line: https://github.com/storybookjs/storybook/blob/3929b4a9c80ec8b883548fecaba63f6228c4db61/app/react/src/client/docs/jsxDecorator.tsx#L123

Screen Shot 2022-07-12 at 21 39 37

and this ilne is imported from react-element-to-jsx-string: https://github.com/algolia/react-element-to-jsx-string/blob/1e3a6089e91226f019907c1def135de7d7c18dfd/src/parser/parseReactElement.js#L96

the package is new after 6.4.22, you can see it's not existed in the 6.4.22 package.json file: https://github.com/storybookjs/storybook/blob/8dd4fa6ef42f803ec276be18fb78644a827d5b74/app/react/package.json#L48-L72

so I guess the bug is from the npm library called react-element-to-jsx-string.

there's a similar issue here: https://github.com/algolia/react-element-to-jsx-string/issues/295#issuecomment-413930085.

daniel-stoian-lgp commented 2 years ago

@zhyd1997 , thank you for the analysis! @shilman, we have a detailed description now of the cause

Kneesal commented 1 year ago

I had a similar issue. However, I managed to fix it doing this:

I am using Storybook 7.3.2

const meta: Meta<typeof Component> = {
  title: 'projectName/Component',
  component: Component,
  parameters: {
    docs: {
      source: { type: 'code' }
    }
  }
}

export default meta;
montik commented 1 year ago

I had a similar issue. However, I managed to fix it doing this:

I am using Storybook 7.3.2

const meta: Meta<typeof Component> = {
  title: 'projectName/Component',
  component: Component,
  parameters: {
    docs: {
      source: { type: 'code' }
    }
  }
}

export default meta;

it works :) black magic 🤣

JoelDSmith commented 11 months ago

I had a similar issue. However, I managed to fix it doing this:

I am using Storybook 7.3.2

const meta: Meta<typeof Component> = {
  title: 'projectName/Component',
  component: Component,
  parameters: {
    docs: {
      source: { type: 'code' }
    }
  }
}

export default meta;

I finally figured out what this was actually doing; it changes the source code view of a story to use the raw source code in the TSX file (including any custom wrapper code you might have), rather than generating the equivalent JSX.

e.g. without:

<Step heading="Recommended Study" />
<Step
  heading="Recommended Study"
  subtitle="Mathematics and Science"
/>

and with:

withDocumentation<typeof Step>({
  description: "A minimal step consists of only an index and heading, with the index defaulting to `1` if not specified",
  args: {
    heading: DEFAULT_ARGS.heading
  }
})
{
  args: {
    heading: DEFAULT_ARGS.heading,
    subtitle: DEFAULT_ARGS.subtitle
  }
}
SalahAdDin commented 8 months ago

I had a similar issue. However, I managed to fix it doing this:

I am using Storybook 7.3.2

const meta: Meta<typeof Component> = {
  title: 'projectName/Component',
  component: Component,
  parameters: {
    docs: {
      source: { type: 'code' }
    }
  }
}

export default meta;

Yeah, It fixes the issue, but why? Why does this happen yet when the argument is an array of objects?

It is related to the accessibility addon:

Objects are not valid as a React child (found: object with keys {label, path}). If you meant to render a collection of children, use an array instead.

mapIntoArray@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:73403:13
mapIntoArray@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:73372:23
mapChildren@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:73432:15
toArray@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:73484:10
parseReactElement@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:78615:54
reactElementToJsxString@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:79083:21
./node_modules/.pnpm/@storybook+react@7.6.14_react-dom@18.2.0_react@18.2.0_typescript@5.3.3/node_modules/@storybook/react/dist/entry-preview-docs.mjs/renderJsx/<@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:4008:24068
./node_modules/.pnpm/next@14.1.0_@babel+core@7.23.9_react-dom@18.2.0_react@18.2.0/node_modules/next/dist/compiled/react/cjs/react.development.js/mapChildren/<@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:73433:17
mapIntoArray@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:73322:31
mapChildren@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:73432:15
renderJsx@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:4008:23769
jsxDecorator@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:4009:1502
hookified@http://localhost:6006/sb-preview/runtime.js:7:18509
decorateStory/<@http://localhost:6006/sb-preview/runtime.js:41:1460
defaultDecorateStory/bindWithContext/<@http://localhost:6006/sb-preview/runtime.js:41:1912
renderWithHooks@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:44758:27
mountIndeterminateComponent@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:50519:13
beginWork$1@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:52119:16
beginWork@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:60528:14
performUnitOfWork@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:59374:12
workLoopSync@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:59090:22
renderRootSync@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:59045:7
recoverFromConcurrentError@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:58262:34
performConcurrentWorkOnRoot@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:58207:26
workLoop@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:75589:42
flushWork@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:75558:14
performWorkUntilDeadline@http://localhost:6006/vendors-node_modules_pnpm_storybook_addon-a11y_7_6_14_node_modules_storybook_addon-a11y_dist_-4276f1.iframe.bundle.js:75867:21

Setting source: { type: 'code' } globally has a problem: it does not show the tsx code by it shows the parameters: image

It is annoying, especially when we want to copy the code from Storybook and use it in our development, to make development faster.

Environment:

Storybook Environment Info:

  System:
    OS: Linux 6.1 Manjaro Linux
    CPU: (16) x64 AMD Ryzen 9 5900HX with Radeon Graphics
    Shell: 5.2.21 - /bin/bash
  Binaries:
    Node: 20.11.0 - ~/.nvm/versions/node/v20.11.0/bin/node
    Yarn: 1.22.21 - /usr/bin/yarn
    npm: 10.2.4 - ~/.nvm/versions/node/v20.11.0/bin/npm
    pnpm: 8.15.1 - /usr/bin/pnpm <----- active
  npmPackages:
    @storybook/addon-a11y: 7.6.13 => 7.6.13 
    @storybook/addon-essentials: 7.6.13 => 7.6.13 
    @storybook/addon-interactions: 7.6.13 => 7.6.13 
    @storybook/addon-links: 7.6.13 => 7.6.13 
    @storybook/addon-onboarding: 1.0.11 => 1.0.11 
    @storybook/addon-storysource: 7.6.13 => 7.6.13 
    @storybook/blocks: 7.6.13 => 7.6.13 
    @storybook/nextjs: 7.6.13 => 7.6.13 
    @storybook/react: 7.6.13 => 7.6.13 
    @storybook/test: 8.0.0-alpha.16 => 8.0.0-alpha.16 
    @storybook/theming: 7.6.13 => 7.6.13 
    eslint-plugin-storybook: 0.6.15 => 0.6.15 
    msw-storybook-addon: 2.0.0-beta.1 => 2.0.0-beta.1 
    storybook: 7.6.13 => 7.6.13 
    storybook-addon-pseudo-states: 2.1.2 => 2.1.2
codeprepai commented 4 months ago

I had a similar issue. However, I managed to fix it doing this: I am using Storybook 7.3.2

const meta: Meta<typeof Component> = {
  title: 'projectName/Component',
  component: Component,
  parameters: {
    docs: {
      source: { type: 'code' }
    }
  }
}

export default meta;

it works :) black magic 🤣

Definetly a black magic