action

用法:

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

任何应用都有action,Actions 可以是修改状态的任何东西。使用 MobX,你可以在你的代码中显式的标记它们,Actions 帮助你更好的组织你的代码结构。它需要一个函数,并之后返回一个其使用untrackedtransactionallowStateChanges包装的函数,建议将它们用于修改可观察的变量或具有任何副作用的任何函数。action还提供了和开发工具组合使用时的调试信息。

注:如果启用 严格模式,则必须使用action去操作 state,详见useStrict。不支持使用@action装饰器在 ES 5.1 setters (i.e. @action set propertyName)

有关操作的详细介绍,请参阅 MobX 2.2 发行版说明

contace-list项目中的两个示例:

    @action createRandomContact() {
        this.pendingRequestCount++;
        superagent
            .get('https://randomuser.me/api/')
            .set('Accept', 'application/json')
            .end(action("createRandomContact-callback", (error, results) => {
                if (error)
                    console.error(error);
                else {
                    const data = JSON.parse(results.text).results[0];
                    const contact = new Contact(this, data.dob, data.name, data.login.username, data.picture)
                    contact.addTag('random-user');
                    this.contacts.push(contact);
                    this.pendingRequestCount--;
                }
            }));
    }

asyncactions 和runInAction

action只影响当前运行的函数,不是当前调度(不是调用)的函数。也就是说,如果你有一个setTimeOut,promise.thenasync构造,在回调中有更多的状态被该改变,这些回调也应该被包含在action中。这可以在上面的"createRandomContact-callback"操作来演示。

如果你使用async/await,这就非常棘手了,因为你不能只是在action中单纯的包装异步函数体了。在这种情况下,runInAction就可以派上用场了,在你打算更新状态的地方使用它就可以了。(但是不要在await中调用这些区块)

举例:

@action /*optional*/ updateDocument = async () => {
    const data = await fetchDataFromUrl();
    /* required in strict mode to be allowed to update state: */
    runInAction("update state after fetching data", () => {
        this.data.replace(data);
        this.isSaving = true;
    })
}

runInAction的另外一种用法是: runInAction(name?, fn, scope?)