元素描述符的 .kind 属性 必须是 "method" 或 "field"

An element descriptor's .kind property must be either "method" or "field"

我正在关注 mobx-react-router 的文档,但是在尝试 运行 我的应用程序时,我在浏览器中收到以下错误:

Uncaught TypeError: An element descriptor's .kind property must be either "method" or "field", but a decorator created an element descriptor with .kind "undefined"
    at _toElementDescriptor (app.js:49988)
    at _toElementFinisherExtras (app.js:49990)
    at _decorateElement (app.js:49980)
    at app.js:49976
    at Array.forEach (<anonymous>)
    at _decorateClass (app.js:49976)
    at _decorate (app.js:49958)
    at Module../src/App/UserStore.js (app.js:50012)
    at __webpack_require__ (bootstrap:19)
    at Module../src/index.js (index.js:1)

这是我初始化的方式:

const appContainer = document.getElementById('app');
if(appContainer) {
  const browserHistory = createBrowserHistory()
  const routingStore = new RouterStore();

  const stores = {
    users: userStore,
    routing: routingStore
  }

  const history = syncHistoryWithStore(browserHistory, routingStore);

  ReactDOM.render(
    (
      <Provider {...stores}>
        <Router history={history}>
          < App />
        </Router>
      </Provider>
    ),
  appContainer);
}

我是这样使用的:

@inject('routing')
@inject('users')
@observer
class App extends Component { ...

我的UserStore:

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

class UserStore {
  @observable users = [];

  @action addUser = (user) => {
    this.users.push(user)
  }

  @computed get userCount () {
    return this.users.length
  }
}

const store = new UserStore();
export default store;

我已尝试 Google 解决此错误,但没有返回任何有用的结果。知道我做错了什么吗?

我像这样更改了 observable 并且它有效(虽然不确定为什么):

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

class UserStore {
  @observable users;

  constructor() {
    this.users = []
  }

  @action addUser = (user) => {
    this.users.push(user)
  }
}

const store = new UserStore();
export default store;

如果您使用 Babel 7 安装装饰器支持:

npm i -D\
  @babel/plugin-proposal-class-properties\
  @babel/plugin-proposal-decorators

然后在您的 .babelrcwebpack.config.js 文件中启用它:

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

请注意,遗留模式很重要(将装饰器提案放在首位也很重要)。非传统模式是 WIP.

参考:https://mobx.js.org/best/decorators.html

虽然已接受的答案有效,但对于来自相同错误消息但上下文不同的任何人来说,这可能是因为随着 the proposal 的进行,装饰者的签名发生了变化。

Using { "legacy": true } 使用一种方法签名,而 {"decoratorsBeforeExport": true } 使用另一种方法签名。这两个标志不兼容。

您可以检查给定示例发生了什么

function log() {
  console.log(arguments)
}
class Foo
  @log
  bar() {
    console.log('hello')
  }
}
new Foo().bar()

使用{"decoratorsBeforeExport": true }会产生

[Arguments] {
  '0': Object [Descriptor] {
    kind: 'method',
    key: 'bar',
    placement: 'prototype',
    descriptor: {
      value: [Function: bar],
      writable: true,
      configurable: true,
      enumerable: false
    }
  }
}

哪里 {"legacy": true } 会给你

[Arguments] {
  '0': Foo {},
  '1': 'bar',
  '2': {
    value: [Function: bar],
    writable: true,
    enumerable: false,
    configurable: true
  }
}

通过使用遗留语义,编写装饰器相当简单。 returns 第 0 个参数是空操作的装饰器。您也可以在返回之前进行变异。使用新语义,您可以如下描述装饰器:

function log(obj) {
  console.log('I am called once, when the decorator is set')
  let fn = obj.descriptor.value
  obj.descriptor.value = function() {
    console.log('before invoke')
    fn()
    console.log('after invoke')
  }
  return obj
}