MobX Quick Start Guide
上QQ阅读APP看书,第一时间看更新

autorun()

autorun() is a long-running side-effect that takes in a function (effect-function) as its argument. The effect-function function is where you apply all your side-effects. Now, these side-effects may depend on one or more observables. MobX will automatically keep track of any change happening to these dependent observables and re-execute this function to apply the side-effect. It's easier to see this in code, as shown here: 

import { observable, action, autorun } from 'mobx';

class Cart {
@observable modified = new Date();
@observable.shallow items = [];

constructor() {
autorun(() => {
console.log(`Items in Cart: ${this.items.length}`);
});
}

@action
addItem(name, quantity) {
this.items.push({ name, quantity });
this.modified = new Date();
}
}

const cart = new Cart();
cart.addItem('Power Cable', 1);
cart.addItem('Shoes', 1);

// Prints:
// Items in Cart: 0
// Items in Cart: 1
// Items in Cart: 2

In the preceding example we are logging an observable (this.items.length) to the console. The logging happens immediately and also any time the observable changes. This is the defining characteristic of autorun(); it runs immediately and also on every change to the dependent observables.

We mentioned earlier that autorun() is a long-running side-effect and continues as long as you don't explicitly stop it. But then, how do you actually stop it? Well, the return-value of autorun() is a function that is in fact a disposer-function. By calling it, you can cancel the autorun() side-effect. Take a look at this:

import { observable, action, autorun } from 'mobx';

class Cart {
/* ... */

cancelAutorun = null;

constructor() {
this.cancelAutorun = autorun(() => {
console.log(`Items in Cart: ${this.items.length}`);
});
}

/* ... */
}

const cart = new Cart();
// 1. Cancel the autorun side-effect
cart.cancelAutorun();

// 2. The following will not cause any logging to happen
cart.addItem('Power Cable', 1);
cart.addItem('Shoes', 1);

// Prints:
// Items in Cart: 0

In the preceding snippet, we are storing the return-value of autorun() (a disposer-function) in a class property: cancelAutorun. By invoking it just after instantiating Cart, we have canceled the side-effect. Now autorun() only prints once, and never again. 

Quick Reader Question: Why does it print only once? Since we are cancelling immediately, shouldn't autorun() skip printing altogether? The answer to this is to refresh the core characteristic of autorun