2016-05-31 36 views
11

Sto utilizzando MobX 2.2.2 per provare a modificare lo stato all'interno di un'azione asincrona. Devo usare useStrict di MobX su true.Utilizzo del decoratore MobX @action con funzioni asincrone e .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) 
    }); 
} 

ottengo:

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 

ho bisogno di fornire il decoratore @Action alla seconda affermazione .then? Qualsiasi aiuto sarebbe apprezzato.

risposta

17

Devo fornire il decoratore @action alla seconda dichiarazione .then? Qualsiasi aiuto sarebbe apprezzato.

Questo è abbastanza vicino alla soluzione reale.

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

dovrebbe essere

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

Tenete a mente action può essere chiamato in molti modi che non sono esclusivi di @action. Da the docs on action:

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

sono una Tutti i modi validi per contrassegnare una funzione come un'azione.

Ecco un bidone che dimostra la soluzione: 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() 

Per quanto riguarda il motivo per cui l'errore si verifica in realtà sto cercando di indovinare che il livello superiore @action non ricorsivamente decorare le funzioni come azioni all'interno della funzione è decorazione, significa che la tua funzione anonima passata nella tua promessa non era in realtà un action.

+1

come fare questo in async/aspettano? – TangMonk

8

Per completare la risposta di cui sopra; infatti, action funziona solo sulla funzione che si passa ad esso. Le funzioni nel then vengono eseguite su uno stack separato e devono pertanto essere riconoscibili come azioni separate.

Si noti che si può anche dare le azioni un nome pure in modo che tu li riconosci facilmente nelle DevTools se si utilizzano quelli:

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

+0

"qui sotto rispondi" * ora: '(lol – m0meni

+0

mi voti vota la tua risposta è completa. Userò i commenti la prossima volta per materiale supplementare .. – mweststrate

+0

Risolto contrassegnando @ AR7 come corretto :) – twsmith

Problemi correlati