Storybook: "babel-plugin-react-docgen" breaks Storybook v6 builds when using the Flow spread operator

Created on 13 Aug 2020  路  9Comments  路  Source: storybookjs/storybook

Observed behavior

Storybook does not build successfully when it parses components using the Flow spread operator.

Expected behavior

I expect Storybook to build successfully.

Details

After upgrading to Storybook v6 and installing the Create React App preset, Storybook fails to build due to an error in babel-loader. Since there were no problems in previous Storybook releases, I think it is safe to assume this is due to new additions in Storybook v6, specifically the addition of react-docgen.

The specifics of the error message are detailed further below, but here is a snapshot of the component and LOC that is raising the issue. Note this component makes heavy use of Flow features, in particular the spread operator.

Example Component

type Props = {|
  ...ComponentProps,
  ...ExtractReturn<typeof mapStateToProps>,
  ...typeof mapDispatchToProps,
|}

class IntroOfferMapObject extends React.PureComponent<Props> {

Resulting Error Trace

yarn run storybook

Module build failed (from ./node_modules/babel-loader/lib/index.js):
TypeError: /MyUser/MyProject/src/components/Map/IntroOfferMapObject.js: Property elements[1] of ArrayExpression expected node to be of a type ["null","Expression","SpreadElement"] but instead got undefined
    at validate (/MyUser/MyProject/node_modules/@babel/types/lib/definitions/utils.js:148:11)
    at validator (/MyUser/MyProject/node_modules/@babel/types/lib/definitions/utils.js:103:7)
    at Object.validate (/MyUser/MyProject/node_modules/@babel/types/lib/definitions/utils.js:229:7)
    at validateField (/MyUser/MyProject/node_modules/@babel/types/lib/validators/validate.js:24:9)
    at validate (/MyUser/MyProject/node_modules/@babel/types/lib/validators/validate.js:17:3)
    at builder (/MyUser/MyProject/node_modules/@babel/types/lib/builders/builder.js:38:27)
    at Object.arrayExpression (/MyUser/MyProject/node_modules/@babel/types/lib/builders/generated/index.js:254:31)
    at buildObjectExpression (/MyUser/MyProject/node_modules/babel-plugin-react-docgen/lib/index.js:146:14)
    at buildObjectExpression (/MyUser/MyProject/node_modules/babel-plugin-react-docgen/lib/index.js:131:60)
    at /MyUser/MyProject/node_modules/babel-plugin-react-docgen/lib/index.js:95:19
    at Array.forEach (<anonymous>)
    at injectReactDocgenInfo (/MyUser/MyProject/node_modules/babel-plugin-react-docgen/lib/index.js:87:17)
    at PluginPass.exit (/MyUser/MyProject/node_modules/babel-plugin-react-docgen/lib/index.js:44:11)
    at newFn (/MyUser/MyProject/node_modules/@babel/traverse/lib/visitors.js:175:21)
    at NodePath._call (/MyUser/MyProject/node_modules/@babel/traverse/lib/path/context.js:55:20)
    at NodePath.call (/MyUser/MyProject/node_modules/@babel/traverse/lib/path/context.js:42:17)

System:

Environment Info:

  System:
    OS: macOS Mojave 10.14.6
    CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
  Binaries:
    Node: 12.9.0 - /usr/local/bin/node
    Yarn: 1.21.1 - ~/.yarn/bin/yarn
    npm: 6.10.2 - /usr/local/bin/npm
  Browsers:
    Chrome: 84.0.4147.125
    Safari: 13.1.2
  npmPackages:
    @storybook/addon-actions: ^6.0.5 => 6.0.5 
    @storybook/addon-knobs: ^6.0.5 => 6.0.5 
    @storybook/addon-links: ^6.0.5 => 6.0.5 
    @storybook/addon-viewport: ^6.0.5 => 6.0.5 
    @storybook/addons: ^6.0.5 => 6.0.5 
    @storybook/preset-create-react-app: ^3.1.4 => 3.1.4 
    @storybook/react: ^6.0.5 => 6.0.5 

Additional context

This build issue can be resolved by removing the react-docgen plugin manually from the webpack config. Observe the following .storybook/main.js file, which removes the react-docgen override from the Storybook webpack configuration:

module.exports = {
  webpackFinal: config => {
    // Manually remove the react-docgen plugin that breaks w/ the
    // Flow spread operator.
    config.module.rules[3].oneOf[1].options.overrides.pop()
    return config
  },
  addons: ['@storybook/preset-create-react-app'],
}

By removing config.module.rules[3].oneOf[1].options.overrides (the react-docgen override), this issue is resolved. I got this workaround from the following issue: https://github.com/storybookjs/storybook/issues/4873#issuecomment-458497220. There are a number of other threads that report this same issue, but they have all been closed with no proper resolution.

bug compatibility with other tools has workaround inactive

All 9 comments

What happens if you add the following to your main.js?

module.exports = {
  typescript: { reactDocgen: false }
}

@shilman Didn't try that before, but looks like it doesn't resolve the issue. Final config for reference:

module.exports = {
  typescript: { reactDocgen: false },
  addons: ['@storybook/preset-create-react-app'],
}

Results in

Module build failed (from ./node_modules/babel-loader/lib/index.js):
TypeError: /MyUser/MyProject/src/components/Map/IntroOfferMapObject.js: Property elements[1] of ArrayExpression expected node to be of a type ["null","Expression","SpreadElement"] but instead got undefined

@koop is this something you can help with?

We're currently running Storybook v6 with Flow successfully (react-docgen doesn't crash, but it also doesn't support extracting info from our spread props).

The first thing I'd try here is isolating what exactly is causing react-docgen to crash. I'd focus on typeof mapStateToProps particular. Can Storybook start when you remove those references? If so, aliasing typeof mapStateToProps might help. (And you might need to declare the alias in a separate file to prevent react-docgen from reading the type.)

Good luck! I'll let you know if we run into anything similar.

@koop Sounds good. I'll try to set up a minimal repro to help isolate what exactly is causing the breakage.

@koop Was able to put together a minimal repro. The issue occurs when using the spread operator with typeof <some object>. Below is the component sample, though I also created a repository with the error isolated to a new CRA app: https://github.com/mgmarlow/stroybook-bug-repro. Interestingly enough, ExtractReturn was not the issue, that form actually works!

Code that causes the issue:

// @flow
import React from "react";

const myObject = {
  foo: "foobar",
};

type Props = {|
  ...typeof myObject, // This is the offending code
|};

const TestComponent = ({ foo }: Props) => {
  return <div>{foo}</div>;
};

export default TestComponent;

Accompanied by this story file:

// @flow
import React from "react";
import TestComponent from "./TestComponent";

export default {
  title: "TestComponent",
  component: TestComponent,
};

export const Primary = () => <TestComponent foo="foobar" />;

Amending by aliasing the type:

As you suggested, the alias does fix the issue. The following compiles as expected:

type MyObjectType = typeof myObject;

type Props = {|
  ...MyObjectType,
|};

Facing similar issue, using spread even in v5 too. I tried fixing it by hack mentioned here, though it fixed the flow issue but it stops rendering Props documentation in addon-docs so can't strip out the babel react plugin too.

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!

Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!

Was this page helpful?
0 / 5 - 0 ratings