2016-05-31 99 views
11

我正在使用MobX 2.2.2來嘗試改變異步操作中的狀態。我將MobX的useStrict設置爲true。使用帶異步函數的MobX @action修飾器和.then

@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) 
    }); 
} 

我得到:

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 

我需要的@action裝飾提供給第二。那麼語句?任何幫助,將不勝感激。

回答

17

我是否需要將@action修飾符提供給第二個.then語句?任何幫助,將不勝感激。

這非常接近實際的解決方案。

.then(json => this.someStateProperty = json) 

應該

.then(action(json => this.someStateProperty = json)) 

記住action可以在許多方面不屬於獨家@action被調用。從the docs on 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() 

至於爲什麼你的錯誤實際發生的事情我猜頂級@action不遞歸裝飾的任何功能,因爲它的裝飾功能範圍內的行爲,這意味着你的匿名功能通過你的承諾並不是真的action

+1

如何做到這一點在異步/的await? 「 – TangMonk

8

補充上述答案;的確,action只適用於你傳遞給它的功能。 then中的函數在單獨的堆棧上運行,因此應該將其識別爲單獨的操作。

注意,你也可以給動作的名稱,以及讓你輕鬆識別它們在devtools如果你使用這些:

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

+0

」下面回答「*現在:'(大聲笑 – m0meni

+0

反對我!你的答案是完整的。下次將使用註釋補充材料.. – mweststrate

+0

通過標記@ AR7修正爲正確:) – twsmith