15

Support for the experimental syntax 'decorators-legacy' isn't currently enabled

I tried adding the decorators-legacy babel plugin and @babel/plugin-proposal-decorators with { legacy: true } in .babelrc but no effect.

Anyone managed to get MobX decorators to work with CRA2?

Brian Burns
  • 14,953
  • 5
  • 69
  • 59
J. Reku
  • 285
  • 1
  • 3
  • 13

9 Answers9

6

Firstly, install dependencies:

yarn add react-app-rewired customize-cra @babel/plugin-proposal-decorators

Secondly, create config-overrides.js in root directory with following contents:

const {
    addDecoratorsLegacy,
    override,
    disableEsLint
} = require("customize-cra");

module.exports = {
    webpack: override(
        addDecoratorsLegacy(),
        disableEsLint()
    )
};

You should be able to use mobx + decorators now.

If you don't have mobx installed already, please run: yarn add mobx mobx-react. Now you can use decorators.

Daniel Kmak
  • 16,209
  • 7
  • 65
  • 83
4

I had same issue and ended up with using mobx4 where Decorators can be used without decorator syntax.

class Store {
  //...
  @action empty() {
    this.data = []
  }

  @action add(e) {
    this.data.push(e)
  }
}

can be rewritten as

class Store {
      //...
       empty() {
        this.data = []
      }

      add(e) {
        this.data.push(e)
      }
    }

decorate(Store, {
  add: action,
  empty: action
})

You can use this feature out of the box from CRA2 and do not need to worry about transform decoracy plugin. Thanks Michel Weststrate for this stuff

https://medium.com/@mweststrate/mobx-4-better-simpler-faster-smaller-c1fbc08008da

sumit
  • 13,148
  • 10
  • 57
  • 103
4

Option 1: Using decorators with CRA v2

If you refer to Mobx documentation, you can get Mobx decorators to work with CRAv2 by using Typescript:

Decorators are only supported out of the box when using TypeScript in create-react-app@^2.1.1.

However, in some cases, you might still face issues when using Mobx with other react frameworks. In that case:

Option 2: Don't use decorators

A detailed step by step guide is documented here.

If you previously defined your observer react component as:

@observer
export default class MyComponent extends React.Component

Change it to:

const MyComponent = observer(class MyComponent extends React.Component{
  /* ... */
});

export default MyComponent;

If you previously had:

@observable myElement = null;

You need to change it to:

myElement;

then:

decorate(MyComponent, {
  myElement: observable,
})

Hope this helps!

Arial
  • 3,746
  • 2
  • 15
  • 16
3

I did an example project of React App 2.0 with Babel 7 and Mobx(with decorators works) without eject! :

Links I used to create this project:

https://github.com/timarney/react-app-rewired/issues/348

https://github.com/arackaf/customize-cra#addbabelpluginsplugins

https://www.leighhalliday.com/mobx-create-react-app-without-ejecting

Almog_0
  • 413
  • 4
  • 10
2

If you use babel 7 you have to add some config in babelrc. Install support for decorators:

npm i --save-dev @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators

And enable it in your .babelrc file:

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

or you can use MobX built-in utility like:

import { observable, computed, action, decorate } from "mobx";

class Timer {
  start = Date.now();
  current = Date.now();

  get elapsedTime() {
    return this.current - this.start + "milliseconds";
  }

  tick() {
    this.current = Date.now();
  }
}
decorate(Timer, {
  start: observable,
  current: observable,
  elapsedTime: computed,
  tick: action
});

I had the same problem and I used mobx-utility and every thing completely worked for me.

Brian Burns
  • 14,953
  • 5
  • 69
  • 59
  • The block of code under "plugins" is the only thing that helped in my case (reactnative 0.61.5). Thanks! – ror Dec 12 '19 at 06:28
2

You don’t have to use more packages, or change configurations.

1- Use decorate in stores – for observable, computed :


import { observable, decorate } from "mobx"

class ToDoStore {
    todos= ["cat","dog"]
}
decorate(ToDoStore, {
    todos: observable,
  });

const store = new ToDoStore()

2- For observer – use the follow class style:

import React from "react"
import { observer } from "mobx-react"

const TodoList = observer(class TodoList extends React.Component {
    render() {
        const {todos} = this.props.store;
        const todoL = todos.map(todo => (<li>{todo}</li>))
        return (
            <div>
            <h1>ToDo List</h1>
            <ul>{todoL}</ul>
            </div>
        );
    }
})
export default TodoList
Citizen-Dror
  • 427
  • 2
  • 12
1

While using CRA2, in order to use MOBX5 you must do following.

npm install -save mobx mobx-react

Now add following lines in your store file.

import {decorate, observable} from "mobx"
import {observer} from "mobx-react"

Now you can use something like this.

class Store {
  //...
}

decorate(Store, {
  list: observable
})

const appStore = new Store()`
Junaid Atique
  • 445
  • 1
  • 5
  • 17
  • Thanks. I can't seem to find a proper tutorial for this other than the MobX 4 blog post that mentions it. Do you know of any good resources? Thanks! – Stephen A. Lizcano Nov 01 '18 at 18:52
1

although others answers are correct if you want to avoid boilerplate code, It's possible to use decorators in CRA2 without ejecting using https://github.com/timarney/react-app-rewired/ and https://github.com/arackaf/customize-cra

landbit
  • 111
  • 2
  • 10
-1

npm run eject

Add the bold line to /config/webpack.config.dev.js around line 162. Make sure to do the same on /config/webpack.config.prod.js otherwise the app won’t build

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

I.dev
  • 397
  • 2
  • 5