storybookjs / storybook

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

Passing multiple components as an array props will crash the app when docs tab is opened. #17482

Open VilleMiekkoja opened 2 years ago

VilleMiekkoja commented 2 years ago

Describe the bug If I pass multiple components as an array prop it will crash the app when docs tab is opened. Basically the browser tab becomes unresponsive, and suggest a warning of unresponsiveness. This did not happen before on version 6.2.9. Also the story inside canvas tab will crash the application if interacted with.

To Reproduce Pass components as an array prop inside your story:

<Button arrayProp={[<Component1 />, <Component2 />]} />

System Environment Info:

System: OS: macOS 11.6 CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz Binaries: Node: 12.18.3 - ~/.nvm/versions/node/v12.18.3/bin/node Yarn: 1.16.0 - /usr/local/bin/yarn npm: 6.14.6 - ~/.nvm/versions/node/v12.18.3/bin/npm Browsers: Chrome: 98.0.4758.80 Firefox: 96.0.3 Safari: 15.0 npmPackages: @storybook/addon-a11y: 6.4.18 => 6.4.18 @storybook/addon-backgrounds: 6.4.18 => 6.4.18 @storybook/addon-viewport: 6.4.18 => 6.4.18

shilman commented 2 years ago

@VilleMiekkoja which framework are you using?

are you rendering your stories in iframe or inline mode? https://storybook.js.org/docs/react/writing-docs/doc-blocks#inline-rendering

have you tried storyStoreV7? https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#story-store-v7

VilleMiekkoja commented 2 years ago

@storybook/react

VilleMiekkoja commented 2 years ago

With this config: docs: { inlineStories: false }, storybook opened the docs tab, but it does not render it fully, and the height is broken for all stories.

I have not tried storyStoreV7, and can't really out of the box, because we have breaking changes at least with the storiesOf method. We dynamically add new components inside a forEach loop, so can't really use the new syntax that easy:

story.add(componentName, () => (
    <>
      <Wrapper>
        {['xs', 's', 'm', 'l', 'xl'].map((size) => (
          <Component key={`icon-black-${size}`} size={size} />
        ))}
      </Wrapper>
      <Wrapper style={{ background: 'var(--color-black)' }}>
        {['xs', 's', 'm', 'l', 'xl'].map((size) => (
          <Component key={`icon-white-${size}`} size={size} style={{ color: '#fff' }} />
        ))}
      </Wrapper>
    </>
  ));
VilleMiekkoja commented 2 years ago

Was able to debug this more. Apparently it has nothing to do with the length of the stories. This is the story that breaks it:

export const WithCustomActions = (args) => {
  const cols = [
    { key: 'id', headerName: 'Not rendered' },
    { key: 'firstName', headerName: 'First name' },
    { key: 'surname', headerName: 'Surname' },
    {
      key: 'age',
      headerName: 'Age',
      transform: ({ age }) => {
        return <div style={{ textAlign: 'right' }}>{age}</div>;
      },
    },
    { key: 'profession', headerName: 'Profession' },
  ];

  const indexKey = 'id';

  const rows: Array<object> = [
    { id: 1000, firstName: 'Lauri', surname: 'Kekkonen', age: 39, profession: 'Engineer' },
    { id: 1001, firstName: 'Maria', surname: 'Sarasoja', age: 62, profession: 'Designer' },
    { id: 1002, firstName: 'Anneli', surname: 'Routa', age: 50, profession: 'Meteorologist' },
    { id: 1003, firstName: 'Osku', surname: 'Rausku', age: 18, profession: 'Mail Carrier' },
  ];

  const [tableRows, setTableRows] = useState(rows);
  const [selectedRows, setSelectedRows] = useState([]);

  const CopySelected = () => (
    <Button
      onClick={() => {
        // eslint-disable-next-line no-console
        console.log('Copy clicked!');
      }}
      style={{
        flexGrow: 0,
      }}
      className="table-custom-action"
      variant="secondary"
      size="small"
      disabled={selectedRows.length === 0}
    >
      Copy selected
    </Button>
  );

  return (
    <div style={{ maxWidth: '640px' }}>
      <Table
        customActionButtons={[<CopySelected key={1} />]}
        selectedRows={selectedRows}
        setSelectedRows={setSelectedRows}
        checkboxSelection
        cols={cols}
        rows={tableRows}
        heading="Employees"
        id="custom-actions"
        indexKey={indexKey}
        renderIndexCol={false}
        variant="dark"
        selectAllRowsText="Select all rows"
        clearSelectionsText="Clear selections"
        ariaLabelCheckboxSelection="Row selection"
      />
    </div>
  );
};

It does not like the customActionButtons. If I set it empty, the docs page will open nicely. Inside Table there is just a simple map used for rendering of the customActionButtons. But I debugged it and it never gets there. It's like the new storybook docs page does not like the idea of passing components as props

VilleMiekkoja commented 2 years ago

I managed to try the storyStoreV7, but no luck, it still freezes. Noticed that the canvas tab story is also buggy; once you select any of the table rows, the browser freezes. I've managed to pinpoint that it does not matter if I use the components that are passed as props or not, it just does not like the passing at all.

VilleMiekkoja commented 2 years ago

This only happens on local mode. So when I run start-storybook. On build mode the problem is gone. With build-storybook there's no problems.

VilleMiekkoja commented 2 years ago

Turns out this happens when you pass multiple components as an array through prop like this:

<Button arrayProp={[<Component1 />, <Component2 />]} />

simonhildebrandt commented 2 years ago

Was stung by this too - given the problems with the docs add-on it seems to make the most sense to discard it.

Now that it's bundled into the essentials add-on, here's a tip for excluding it there:

  "addons": [
    "@storybook/addon-essentials",
    ...
  ],

...becomes...

  "addons": [
    {
      name: '@storybook/addon-essentials',
      options: {
        docs: false, // Disabling due to https://github.com/storybookjs/storybook/issues/17098 and other errors
      },
    },
    ...
  ],

(Found here: https://stackoverflow.com/a/66188323/1300227 )

lordfpx commented 2 years ago

Exact same issue here :-(

Jasperrr91 commented 2 years ago

Same issue here with React 17. Like @VilleMiekkoja mentioned, it works just fine in production mode but when serving with start-storybook this issue arises. Haven't been able to track it down yet.

DrUNE commented 2 years ago

In this example it hangs browser when you try to edit text in input:

export interface TextInputProps extends InputHTMLAttributes<HTMLInputElement> {
  icons?: React.ReactNode | React.ReactNode[];
}
const MyInput = React.forwardRef<HTMLInputElement, TextInputProps>(({ icons, ...props }, ref) => {
  return <input ref={ref} {...props} />;
});

const Template: ComponentStory<typeof TextInput> = (props) => {
  const [localValue, setValue] = useState<string>('');

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    const inputValue = e.target.value;
    setValue(inputValue);
  };

  const icons = [<div />, <div />];

  return <MyInput value={localValue} onChange={handleChange} icons={icons} />;
};

@storybook/react@6.5.10

shilman commented 1 year ago

Yowza!! I just released https://github.com/storybookjs/storybook/releases/tag/v7.0.0-beta.26 containing PR #19188 that references this issue. Upgrade today to the @next NPM tag to try it out!

npx sb@next upgrade --prerelease

Closing this issue. Please re-open if you think there's still more to do.

mivd7 commented 1 year ago

This issue still persists when passing in a ReactNode array as prop through the args object in a story @ version 7.1.0. When defining a const variable with a ReactNode array inside a Story component it doesn't.