storybook: Decorators syntax usage is broken

Describe the bug When trying to write a story that contains code using decorators syntax (In this case Mobx - the decorators works totally fine in the project) it throws an error:

index.js:39 Error: Decorating class property failed. Please ensure that proposal-class-properties is enabled and set to use loose mode. To use proposal-class-properties in spec mode with decorators, wait for the next major version of decorators in stage 2.

The babel configuration in .babelrc is correct, the file is read:

{
  "plugins": [
    "@babel/plugin-syntax-dynamic-import",
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose": true }],
    "babel-plugin-styled-components",
    "@babel/plugin-proposal-export-default-from",
    "@babel/plugin-transform-async-to-generator",
    "@babel/plugin-transform-classes",
    "@babel/plugin-transform-runtime"
  ],
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "modules": false
      }
    ],
    "@babel/preset-react"
  ],
}

To Reproduce Steps to reproduce the behavior:

  1. Create story using the decorator
  2. Try open it - error in the console

Expected behavior Decorators can be used.

System:

  • OS: Ubuntu
  • Framework: react
  • Addons: [actions, viewport]
  • Version: 5.0.1

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 24 (5 by maintainers)

Most upvoted comments

I’m also using create-react-app, mobx and storybook and having issues with decorators.

I managed to get around this by having duplicate .babelrc files. The first babelrc is in my root directory contianing:

{
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose" : true }],
    "babel-plugin-styled-components"
  ],
  "presets": [
    "babel-preset-react-app"
  ]
}

The second .babelrc file I put in my .storybook directory looks like:

{
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }, "p1"],
    ["@babel/plugin-proposal-class-properties", { "loose" : true }, "p2"],
    ["babel-plugin-styled-components", {},  "p3"]
  ],
  "presets": [
    ["babel-preset-react-app", {}, "p4"]
  ]
}

I had to give everything alias name so it didn’t clash with the root level babelrc.

So far things look good…

Well 😄 Actually what I post in the first commit is IMHO the minimal babelrc config that reproduces the problem.

In the repo is only ejected CRA, initiated storybook with https://github.com/storybooks/storybook/tree/next/app/react and added babel config to package.json

  "babel": {
    "plugins": [
      [
        "@babel/plugin-proposal-decorators",
        {
          "legacy": true
        }
      ],
      [
        "@babel/plugin-proposal-class-properties",
        {
          "loose": true
        }
      ]
    ],
    "presets": [
      "react-app"
    ]
  }

The actual code that reproduces it is in src/stories/index.js and it is simply:

class Test {
  @observable x = 1
}

const xxx = new Test();

There have to be something with storybook internals, I guess. Probably MobX itself is doing nothing wrong here. I ping you after @pgoforth comment because I thought that maybe you’ve seen similar case before. Let’s wait for some maintainers answer @shilman

This likely has to do with legacy implementation of @babel/plugin-proposal-decorators. I’m working on a project using the latest decorator proposal and everything works fine:

['@babel/plugin-proposal-decorators', {
    legacy: false,
    decoratorsBeforeExport: false,
    version: 'jan-2019'
}]

@darkowic When I use this in your babel config in that test repo, the error is gone:

{
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": false,
        "decoratorsBeforeExport": false,
        "version": "jan-2019"
      },
    ],
    [
      "@babel/plugin-proposal-class-properties",
      {
        "loose": true
      }
    ]
  ],
  "presets": [
    "react-app"
  ]
}

I realize you need to use legacy decorators, but maybe there’s a different legacy config that will work for you.

@darkowic I can’t tell if you found the solution to your issue, but I was experiencing the same problem.

After struggling for a while, I found this comment https://github.com/babel/babel/issues/8577#issuecomment-439579410 which helped lead me to the solution that worked for me.

Adding the plugins to .babelrc was not enough. I needed to create a custom .storybook/webpack.config.js and add the plugins there. Once I had the custom webpack config, the error was gone and the stories were working properly.

@darkowic this is not what maintainers typically call a minimal reproduction 😉. Can you link to the babel config in that repo?

Edit: or is a blank storybook that large? Sorry, zero experience with storybook, just wanted to peek at the babel config to see if there is something obvious

I’m also using create-react-app, mobx and storybook and having issues with decorators.

I managed to get around this by having duplicate .babelrc files. The first babelrc is in my root directory contianing:

{
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose" : true }],
    "babel-plugin-styled-components"
  ],
  "presets": [
    "babel-preset-react-app"
  ]
}

The second .babelrc file I put in my .storybook directory looks like:

{
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }, "p1"],
    ["@babel/plugin-proposal-class-properties", { "loose" : true }, "p2"],
    ["babel-plugin-styled-components", {},  "p3"]
  ],
  "presets": [
    ["babel-preset-react-app", {}, "p4"]
  ]
}

I had to give everything alias name so it didn’t clash with the root level babelrc.

So far things look good…

@richardwardza Tried every solution around and yours is the only one that worked for me, Thaks a Lot!!

Just met the same issue with create-react-app created React projects.

The issue is about the order of overriding options passed to babel-loader. If it is a create-react-app project, @storybook/react would detect if react-scripts is present. If yes, it will load the options from react-scripts package. As you might know, react-scripts from create-react-app has configured babel options as below.

{
  "plugins": [
    ["@babel/plugin-proposal-decorators"],
    ["@babel/plugin-proposal-class-properties", { "loose" : true }],
  ]
}

The default option for @babel/plugin-proposal-decorators is with legacy flag false.

The babel configuration from react-scripts come after customized storybook .babelrc. That is why .babelrc from storybook is not picking the legacy flag.

The work-round for me is to eject create-react-app project for now. After ejection, react-scripts is no longer there.

@darkowic note that error in the screenshot actually signals that it should be in loose mode, which is also in your config, which seems to suggest the config isn’t actually picked up? MobX requires loose mode, that is correct. It seems that that is what storybook expects as well from the above message.

(loose mode is also the typescript behavior, and with loose mode it is easier to change descriptors with decorators, which is harder in strict mode, which seems to be a problem with the spec that sadly not everybody agrees upon, but it’s on hold now anyway)

@darkowic I don’t know what to tell you. I can use decorators on static properties in my codebase and everything works fine in Storybook. However, I am not using Mobx and I am using the latest decorators spec. This seems like more of an incompatibility between Mobx (or a dependency thereof) and Storybook.

I did notice one thing. When using @babel/plugin-proposal-class-properties in loose mode, it does not use Object.defineProperty. That may have some bearing on the effectiveness of decorators, since they are used for modifying property descriptors. Hopefully this leads you in the right direction, but like @mweststrate implied, without code to test against, we can only guess what’s causing the issue.[Update] Looking through your repo now

Looks superficially fine (assuming it is using babel 7, not 6). Maybe the config is not picked up at all from that place? Anyway, leaving it to the storybook maintainers for now… 😃

legacy should be true. Beyond that, share setup and example or didn’t happen.