Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Circular references in React prop data causes stack overflow error in v6 #12747

Closed
jonrimmer opened this issue Oct 12, 2020 · 14 comments · Fixed by algolia/react-element-to-jsx-string#660 or #16407

Comments

@jonrimmer
Copy link
Contributor

jonrimmer commented Oct 12, 2020

Describe the bug

If a data structure with a circular reference is supplied a prop to a React component, Storybook will error with a Maximum call stack size exceeded error.

To Reproduce

  1. Create a simple data structure with a circular reference:
const parent = {}
const child = {};
parent.child = child;
child.parent = parent;
  1. Supply it as a prop to a React component in a Storybook story, such as the Button story created by sb init:
export const Primary = (args) => <Button data={parent} />;

Opening the story will produce an error of the form:

Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
    at sortObject (http://localhost:6007/vendors~main.7760bc58b9f4eb7ba920.bundle.js:43938:20)
    at http://localhost:6007/vendors~main.7760bc58b9f4eb7ba920.bundle.js:43965:21
    at Array.reduce (<anonymous>)
    at sortObject (http://localhost:6007/vendors~main.7760bc58b9f4eb7ba920.bundle.js:43955:36)
    at http://localhost:6007/vendors~main.7760bc58b9f4eb7ba920.bundle.js:43965:21
    at Array.reduce (<anonymous>)
    at sortObject (http://localhost:6007/vendors~main.7760bc58b9f4eb7ba920.bundle.js:43955:36)
    at http://localhost:6007/vendors~main.7760bc58b9f4eb7ba920.bundle.js:43965:21
    at Array.reduce (<anonymous>)
    at sortObject (http://localhost:6007/vendors~main.7760bc58b9f4eb7ba920.bundle.js:43955:36)

Expected behavior

The Story should work without errors.

Code snippets

A simple repro repo is here:

https://github.com/jonrimmer/storybook-v6-is-broken

System

  Binaries:
    Node: 13.8.0 - ~/.nvm/versions/node/v13.8.0/bin/node
    Yarn: 1.22.0 - /usr/local/bin/yarn
    npm: 6.13.6 - ~/.nvm/versions/node/v13.8.0/bin/npm
  Browsers:
    Chrome: 86.0.4240.75
    Safari: 14.0
  npmPackages:
    @storybook/addon-actions: ^6.0.26 => 6.0.26 
    @storybook/addon-essentials: ^6.0.26 => 6.0.26 
    @storybook/addon-links: ^6.0.26 => 6.0.26 
    @storybook/node-logger: ^6.0.26 => 6.0.26 
    @storybook/preset-create-react-app: ^3.1.4 => 3.1.4 
    @storybook/react: ^6.0.26 => 6.0.26 

Additional context

This worked fine in v5. The error seems to be happened because Storybook is trying to use react-element-to-jsx-string to serialize the story. This will obviously not work with many data structures.

@shilman
Copy link
Member

shilman commented Oct 12, 2020

Thanks for the repro! As a temporary workaround you should be able to set the docs.source.type parameter to "code"

@shilman shilman self-assigned this Oct 15, 2020
@shilman shilman added this to the 6.1 docs milestone Oct 22, 2020
@shilman
Copy link
Member

shilman commented Nov 2, 2020

duplicate repro from @arcanis

import React from 'react';

export default {
  title: `Something`,
};

function TestComponent() {
  return <>Hello World</>;
}

const selfReferencing: { self?: any } = {};
selfReferencing.self = selfReferencing;

export const Breaks = (args: any) => {
  return (
    <>
      <TestComponent thisPropDoesntEvenExist={selfReferencing} />
    </>
  );
};

@shilman shilman modified the milestones: 6.1 docs, 6.2 docs Nov 24, 2020
@Git-me-outta-here
Copy link

Thank you for the workaround 👍

I have had the same problem with THREEjs, the meshes have circular references.

Just to specify what @shilman means by "doc.source.type" parameter:
example

@stale
Copy link

stale bot commented Dec 25, 2020

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

@stale stale bot added the inactive label Dec 25, 2020
@ayelenmarie
Copy link

Thanks for the repro! As a temporary workaround you should be able to set the docs.source.type parameter to "code"

Hi @shilman ! This workaround seems not to work with .addParameters(). I'm using it like so in the story:
.addParameters({ docs: { source: { type: 'code', }, }, })

Is there maybe a different approach I can take? I'm having this same issue with several stories that I need to solve. Thanks!

@stale stale bot removed the inactive label Jan 5, 2021
@gerardo-navarro
Copy link

gerardo-navarro commented Mar 1, 2021

duplicate repro from @arcanis

import React from 'react';

export default {
  title: `Something`,
};

function TestComponent() {
  return <>Hello World</>;
}

const selfReferencing: { self?: any } = {};
selfReferencing.self = selfReferencing;

export const Breaks = (args: any) => {
  return (
    <>
      <TestComponent thisPropDoesntEvenExist={selfReferencing} />
    </>
  );
};

I also face this issue using @storybook/[email protected] in combination with [email protected] with [email protected]. I also received the mentioned error RangeError: Maximum call stack size exceeded. I was able to apply the workaround and continue to work. I think the problem lies with react-bootstrap.

My story looks like this.

import React from 'react'
import { Story, Meta } from '@storybook/react/types-6-0'
import { FormProvider, useForm, useFormContext } from 'react-hook-form'
import { Form } from 'react-bootstrap'

export default {
  title: 'FormFields/Test',
  component: TestInput
  // This is a workaround for the issue regarding "Maximum call stack size exceeded"
  // See https://github.com/storybookjs/storybook/issues/12747
  //
  // parameters: { docs: { source: { type: 'code' } } }
} as Meta

const TestInput = () => {
  const { register } = useFormContext()
  return (
    <Form.Control
      name='testFld1'
      type='text'
      ref={register({ required: 'Dies ist ein Pflichtfeld.' })}
    />
  )
}

const Template: Story = (args) => {
  return <TestInput />
}

export const Empty = Template.bind({})
Empty.decorators = [
  (Story) => {
    const rhFormMethods = useForm()
    const onSubmit = (data) => console.log(data)
    return (
      <FormProvider {...rhFormMethods}>
        <form noValidate onSubmit={rhFormMethods.handleSubmit(onSubmit)}>
          <Story />
          <input type='submit' />
        </form>
      </FormProvider>
    )
  }
]
Empty.args = {}

@shilman shilman modified the milestones: 6.2 docs, 6.2 candidates Mar 4, 2021
@kluplau
Copy link

kluplau commented Mar 23, 2021

@shilman Will circular references be working again in 6.2?

@jacknewberry
Copy link

jacknewberry commented May 21, 2021

I had the same issue with react-hook-form and storybook.

The "Maximum callstack exceeded" error was resolved by setting docs.source.type to "code" as described. (Although I have no idea what other impact this may have)

I have read elsewhere that for react-hook-form, the issue may be due to a react ref being passed in props, causing storybook's sortObject method to try to sort the DOM!

Another report of this issue between react-hook-form and storybook - https://www.gitmemory.com/issue/react-hook-form/react-hook-form/4449/803590957

@Andarist
Copy link
Contributor

The problem is in the react-element-to-jsx-string package. Specifically in its recursive sortObject function that is used within its formatComplexDataStructure function.

I've just prepared a couple of other PRs for this package but as far as I can tell it is a little bit abandoned at the moment. This one wouldn't be a hard problem to fix and I might do it as well - if they merge those other PRs. At the moment investing time in that seems like a possible waste so I'm waiting to see if there is any activity in that project.

@Andarist
Copy link
Contributor

And here is the fix for the issue: algolia/react-element-to-jsx-string#660 . At least for the one initially reported by @jonrimmer here.

@shilman
Copy link
Member

shilman commented Oct 20, 2021

Son of a gun!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.4.0-beta.16 containing PR #16407 that references this issue. Upgrade today to the @next NPM tag to try it out!

npx sb upgrade --prerelease

@cereallarceny
Copy link

This is very much still a problem @shilman. Only fix I've been able to ascertain is using:

parameters: {
  docs: {
    source: {
      type: 'code'
    }
  }
}

I cannot find what this does anywhere in the docs...

@Andarist
Copy link
Contributor

Please always try to share a repro case in a runnable form - either by providing a git repository to clone or a codesandbox. OSS maintainers usually can't afford the time to set up the repro, even if exact steps are given.

@thexpand
Copy link

Setting the parameters.docs.source.type to code did the trick for me, but I can't understand why. I found this in the API docs:
https://storybook.js.org/docs/react/api/doc-block-source#type

By I still don't understand what's the difference between code and dynamic. Anyone care to explain?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment