2016-05-31 11 views
11

Używam MobX 2.2.2, aby spróbować zmutować stan wewnątrz akcji asynchronicznej. Mój zestaw useStrict MobX ma wartość true.Używanie dekoratora MobX @action z funkcjami asynchronicznymi i. 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) 
    }); 
} 

uzyskać:

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 

Czy muszę dostarczyć dekorator @action do drugiego .Następnie stwierdzeniem? Każda pomoc będzie doceniona.

Odpowiedz

17

Czy muszę dostarczyć dekorator @ action do drugiego zdania. Then? Każda pomoc będzie doceniona.

Jest to całkiem blisko rzeczywistego rozwiązania.

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

powinny być

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

Pamiętaj action można wywołać na wiele sposobów, które nie wykluczają się @action. Od the docs on action:

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

są Poprawne sposoby oznaczania funkcji jako działania.

Oto bin demonstrując rozwiązanie: 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() 

Jak, dlaczego twój błąd rzeczywiście dzieje Zgaduję, że górny poziom @action nie rekurencyjnie ozdobić żadnych funkcji jako działania wewnątrz funkcji jest to zdobienie, co oznacza, że ​​twoja anonimowa funkcja przeszła w twoją obietnicę, tak naprawdę nie była to action.

+1

jak to zrobić w asynchroniczny/Oczekujcie? – TangMonk

8

Aby uzupełnić powyższą odpowiedź; w rzeczy samej, action działa tylko na funkcji, którą do niego przekazujesz. Funkcje w then są uruchamiane na osobnym stosie i powinny być rozpoznawalne jako oddzielne akcje.

pamiętać, że można również podać nazwę działań, a także, dzięki czemu łatwo je rozpoznać w DevTools jeśli używasz tych:

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

+0

"poniżej odpowiedź" * teraz: "(lol – m0meni

+0

dół do głosowania mnie! Twoja odpowiedź jest kompletna. Użyje komentarzy następnym razem do uzupełnienia rzeczy .. – mweststrate

+0

Naprawiono przez oznaczenie @ AR7 jako poprawne :) – twsmith

Powiązane problemy