Javascript 将MobX@action decorator与异步函数一起使用,然后
我正在使用Mobx2.2.2尝试在异步操作中改变状态。我已将MobX的useStrict设置为trueJavascript 将MobX@action decorator与异步函数一起使用,然后,javascript,mobx,Javascript,Mobx,我正在使用Mobx2.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.someStatePro
@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
我是否需要向第二个.then语句提供@action decorator?任何帮助都将不胜感激
我是否需要向第二个.then语句提供@action decorator?任何帮助都将不胜感激
这与实际解决方案非常接近
.then(json => this.someStateProperty = json)
应该是
.then(action(json => this.someStateProperty = json))
请记住,action
可以通过多种方式调用,而这些方式并不是@action
独有的。发件人:
action(fn)
动作(名称,fn)
@action classMethod
@action(name)classMethod
@action boundClassMethod=(args)=>{body}
@action(name)boundClassMethod=(args)=>{body}
至于您的错误实际发生的原因,我猜想顶级的
@action
不会递归地将任何函数修饰为它所修饰的函数中的操作,这意味着传递到承诺中的匿名函数实际上不是一个操作
来补充上述答案;实际上,action
只对传递给它的函数起作用。then
中的函数在单独的堆栈上运行,因此应可识别为单独的操作
请注意,如果您使用以下操作,还可以为这些操作命名,以便在devtools中轻松识别它们:
然后(操作(“获取后更新对象”,json=>this.someStateProperty=json))
注意,在异步方法中,您必须手动在等待某项操作后启动新操作/事务:
@mobx.action async someAsyncFunction(args) {
this.loading = true;
var result = await fetch(`http://localhost:8080/some_url`, {
method: 'POST',
body: {
args
}
});
var json = await result.json();
@mobx.runInAction(()=> {
this.someStateProperty = json
this.loading = false;
});
}
我的偏好
我不喜欢直接使用@mobx.action/runInAction,但总是将其放在private
方法上。让公共方法调用实际更新状态的私有方法:
public someAsyncFunction(args) {
this.startLoading();
return fetch(`http://localhost:8080/some_url`, {
method: 'POST',
body: {
args
}
})
.then(res => res.json())
.then(this.onFetchResult);
}
@mobx.action
private startLoading = () => {
this.loading = true;
}
@mobx.action
private onFetchResult = (json) => {
this.someStateProperty = json;
this.loading = false;
}
投我一票!你的答案是完整的。下次将使用评论作为补充内容。@mweststrate哈哈,我永远不会否决投票。如果您没有使用MobX,我无法回答。递归地将
操作
应用于函数有意义吗?Bluebird在promisifyAll()
上做了类似的事情,而且非常方便。一开始我认为它不会破坏userict(true)
的意图。如何在async/await中做到这一点?很好的方法,但是public
和private
只存在于TS中。@VitorLuizC在javascript中是可能的,但它会变得混乱(使私有方法变得混乱)。您需要在构造函数方法作用域中定义私有方法,使用它的公共方法也必须在构造函数本身中创建。
public someAsyncFunction(args) {
this.startLoading();
return fetch(`http://localhost:8080/some_url`, {
method: 'POST',
body: {
args
}
})
.then(res => res.json())
.then(this.onFetchResult);
}
@mobx.action
private startLoading = () => {
this.loading = true;
}
@mobx.action
private onFetchResult = (json) => {
this.someStateProperty = json;
this.loading = false;
}