2016-05-31 17 views
11

Ich benutze MobX 2.2.2, um zu versuchen, den Status innerhalb einer asynchronen Aktion zu ändern. Ich habe MobX useStrict auf wahr gesetzt.Verwenden des MobX @action Dekorators mit asynchronen Funktionen und dann

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

ich:

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 

Muss ich den @action Dekorateur auf die zweite .then Erklärung liefern? Jede Hilfe wäre willkommen.

Antwort

17

Muss ich den @action Decorator der zweiten .then-Anweisung liefern? Jede Hilfe wäre willkommen.

Dies ist ziemlich nah an der tatsächlichen Lösung.

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

sollte

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

Beachten Sie action kann auf vielfältige Weise genannt werden, die @action nicht ausschließen. Von the docs on action:

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

sind Es gibt gültige Möglichkeiten, eine Funktion als Aktion zu markieren.

Hier ist eine bin die Lösung demonstriert: 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() 

Was, warum Ihre Fehler dekorieren, tatsächlich passiert Ich vermute, dass die Top-Level-@action nicht rekursiv dekorieren alle Funktionen als Aktionen innerhalb der Funktion ist es was bedeutet, dass Ihre anonyme Funktion in Ihr Versprechen übernommen wurde, war nicht wirklich ein action.

+1

, wie dies zu tun in async/await? – TangMonk

8

Um die obige Antwort zu ergänzen; In der Tat funktioniert action nur auf die Funktion, die Sie an es übergeben. Die Funktionen in der then werden auf einem separaten Stack ausgeführt und sollten daher als separate Aktionen erkennbar sein.

Beachten Sie, dass Sie auch die Aktionen einen Namen geben kann, als auch, so dass Sie sie leicht in den devtools erkennen, wenn Sie diejenigen verwenden:

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

+0

"unter der Antwort" * jetzt: '(lol – m0meni

+0

down vote mich! Ihre Antwort ist die vollständige. Wird Kommentare nächstes Mal für ergänzende Sachen .. – mweststrate

+0

Fixed durch die Kennzeichnung @ AR7 als richtig :) – twsmith