使用带有异步函数和.then的MobX @action装饰器

tws*_*ith 14 javascript mobx

我正在使用MobX 2.2.2尝试在异步操作中改变状态.我将MobX的useStrict设置为true.

@action someAsyncFunction(args) {
  fetch(`http://localhost:8080/some_url`, {
    method: 'POST',
    body: {
      args
    }
  })
  .then(res => res.json())
  .then(json => this.someStateProperty = json)
  .catch(error => {
    throw new Error(error)
  });
}
Run Code Online (Sandbox Code Playgroud)

我明白了:

Error: Error: [mobx] Invariant failed: It is not allowed to create or change state outside an `action` when MobX is in strict mode. Wrap the current method in `action` if this state change is intended
Run Code Online (Sandbox Code Playgroud)

我是否需要将@action装饰器提供给第二个.then语句?任何帮助,将不胜感激.

m0m*_*eni 19

我是否需要将@action装饰器提供给第二个.then语句?任何帮助,将不胜感激.

这与实际解决方案非常接近.

.then(json => this.someStateProperty = json)
Run Code Online (Sandbox Code Playgroud)

应该

.then(action(json => this.someStateProperty = json))
Run Code Online (Sandbox Code Playgroud)

请记住,action可以通过许多非独有的方式调用@action.从文档中的行动:

  • action(fn)
  • action(name, fn)
  • @action classMethod
  • @action(name) classMethod
  • @action boundClassMethod = (args) => { body }
  • @action(name) boundClassMethod = (args) => { body }

都是将函数标记为动作的有效方法.

这是一个展示解决方案的垃圾箱:http://jsbin.com/peyayiwowu/1/edit?js,output

mobx.useStrict(true);
const x = mobx.observable(1);

// Do async stuff
function asyncStuff() {
  fetch('http://jsonplaceholder.typicode.com/posts')
    .then((response) => response.json())
    // .then((objects) => x.set(objects[0])) BREAKS
    .then(mobx.action((objects) => x.set(objects[0])))
}

asyncStuff()
Run Code Online (Sandbox Code Playgroud)

至于为什么你的错误实际发生我猜测顶级@action不会递归地装饰任何函数作为它正在装饰的函数内的动作,这意味着你的匿名函数传递到你的诺言并不是真的action.


mwe*_*ate 9

补充上述答案; 实际上,action只适用于您传递给它的功能.其中的函数在then单独的堆栈上运行,因此应该可以识别为单独的操作.

请注意,您还可以为操作指定名称,以便在使用这些操作时在devtools中轻松识别它们:

then(action("update objects after fetch", json => this.someStateProperty = json))