storybook icon indicating copy to clipboard operation
storybook copied to clipboard

Too much recursion

Open haf opened this issue 3 years ago • 5 comments

Describe the bug For one component I have the UI crashes when running with Storybook.

To Reproduce Please create a reproduction repo by running npx sb@next repro and following the instructions. When you're done, please link the repo here. We prioritize issues with reproductions over those without.

System

Info:

$ npx sb@next info

Environment Info:

  System:
    OS: macOS 10.15.7
    CPU: (12) x64 Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz
  Binaries:
    Node: 14.17.0 - ~/.nvm/versions/node/v14.17.0/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.13 - ~/.nvm/versions/node/v14.17.0/bin/npm
  Browsers:
    Firefox: 88.0.1
    Safari: 14.1
  npmPackages:
    @storybook/addon-actions: ^6.2.9 => 6.2.9
    @storybook/addon-essentials: ^6.2.9 => 6.2.9
    @storybook/addon-links: ^6.2.9 => 6.2.9
    @storybook/react: ^6.2.9 => 6.2.9

Browser: Firefox

Additional context image

image
Uncaught InternalError: too much recursion
    isArguments es5-shim.js:1084
    keys es5-shim.js:1147
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:300
    sortObject index.js:314
    sortObject index.js:304
    sortObject index.js:314
    sortObject index.js:304
es5-shim.js:1084
    call self-hosted:1173
    isArguments es5-shim.js:1084
    keys es5-shim.js:1147
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221
    sortObject index.js:300
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    sortObject index.js:314
    reduce self-hosted:257
    sortObject index.js:304
    map self-hosted:221

Inputs

image

Seems to hang on a property that's a combination of a self-referencing object inside of an array, inside the rendered props of <Line

image

This components comes from react-chartjs-2.

I have this storybook config:

const path = require("path")

module.exports = {
  "stories": [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "storybook-addon-apollo-client"
  ],
  webpackFinal: async (config, { configType }) => {
    return {
      ...config,
      resolve: {
        ...config.resolve,
        alias: {
          ...config.resolve?.alias,
          lib: path.resolve(__dirname, '../src/lib'),
          components: path.resolve(__dirname, '../src/components')
        }
      }
    }
  }
}

The solution to this bug is to track and avoid cyclic objects:

https://stackoverflow.com/questions/14962018/detecting-and-fixing-circular-references-in-javascript

There seems to be some kind of tracking already, but only on a key "owner": however, it would seem the data structure from the components is passed in as-is, which means it doesn't have Storybook-specific naming practises for the properties, and therefore crashes.

haf avatar May 26 '21 11:05 haf

I'm encountering this issue as well.

I have tried I'm running v6.2.9 and v6.3.7 and is seeing the same issue.

image

Interestingly enough, this story doesn't trigger the error:

export const Basic = () => {
  return <p>Was he slow?</p>;
};

As soon as I add a props argument, it starts to fail with the error too much recursion. Any of these triggers the error:

export const Basic = (props) => {
  return <p>Was he slow?</p>;
};

export const Basic = ({ a, b, c }) => {
  return <p>Was he slow?</p>;
};

What I noticed, commenting out each part of the story one by one is that I had a decorator for next/router set up like this:

export default {
  title: '...',
  decorators: [
    withNextRouter,
  ],
};

// ...

export const withNextRouter = (storyFn, value) => (
  <RouterContext.Provider value={{ query: {}, asPath: '/', prefetch: async () => {}, ...value }}>
    {storyFn()}
  </RouterContext.Provider>
);

Removing value, it does seem to error anymore!

adrienrn avatar Sep 02 '21 15:09 adrienrn

I'm experiencing the same issue when using @emotion/styled:

import styled from "@emotion/styled";
import React from "react";

const StyledHeader = styled.h1();
const StyledButton = styled.button();
const StyledFooter = styled.div()

const SimpleComponent = ({ header, footer, Header }) => (
  <>
    {header}
    { Header && <Header />}
    <div>Div</div>
    {/* works fine */}
    <StyledButton>Button</StyledButton>
    {footer}
  </>
);

export default {
  title: "Recursion",
  component: SimpleComponent,
};

const Template = ({ getHeader, ...args }) => {
  // no issue here
  const footer = <StyledFooter>Footer</StyledFooter>
  const header = getHeader?.()
  
  return <SimpleComponent header={header} footer={footer} {...args}/>
};

export const BuggyWithStyledElement = Template.bind({});
BuggyWithStyledElement.args = {
  header: <StyledHeader>Styled Header</StyledHeader>,
};

export const NotBuggyWithoutStyledElement = Template.bind({});
NotBuggyWithoutStyledElement.args = {
  header: <h1>Unstyled Header</h1>,
};

export const NotBuggyWithStyledElementWrapped = Template.bind({});
NotBuggyWithStyledElementWrapped.args = {
  Header: () => <StyledHeader>Styled Header 2</StyledHeader>,
};

export const NotBuggyWithStyledElementGetter = Template.bind({});
NotBuggyWithStyledElementGetter.args = {
  getHeader: () => <StyledHeader>Styled Header 3</StyledHeader>,
};

In the first story we're passing a styled component as prop and it's causing issues. It doesn't cause issues when we're using vanilla h1. It also doesn't cause issues when wrapping it.

Maykin-99 avatar Sep 28 '21 10:09 Maykin-99

I started getting this error when I added @storybook/addon-docs to the addons array. The story worked fine without it, but on startup storybook complains if that addon is not in the addons.

rally25rs avatar Oct 12 '21 18:10 rally25rs

I was able to fix this issue with the line

export const parameters = { docs: { source: { type: 'code' } } };

I followed this comment here https://github.com/storybookjs/storybook/issues/12040#issuecomment-674321425

austinmccalley avatar Dec 28 '21 18:12 austinmccalley

I was having the same problem a simple react-hook-form using tailwind.

Thanks @austinmccalley , your fix worked and you saved me a lot of time!

ngirardin avatar Sep 20 '22 07:09 ngirardin