Decorating actions
The use of decorators is pervasive in MobX. Actions also get special treatment with the @action decorator to mark class methods as actions. With decorators, the Cart class can be written as shown here:
class Cart {
@observable modified = new Date();
@observable.shallow items = [];
@action
addItem(name, quantity) {
this.items.push({ name, quantity });
this.modified = new Date();
}
@action.bound
removeItem(name) {
const item = this.items.find(x => x.name === name);
if (item) {
item.quantity -= 1;
if (item.quantity <= 0) {
this.items.remove(item);
}
}
}
}
In the preceding snippet, we used @action.bound for the removeItem() action. This is a special form that pre-binds the instance of the class to the method. This means you can pass around the reference to removeItem() and be assured that the this value always points to the instance of the Cart.
A different way of declaring the removeItem action with a pre-bound this is with the use of class properties and arrow-functions. This can be seen in the following code:
class Cart {
/* ... */
@action removeItem = (name) => {
const item = this.items.find(x => x.name === name);
if (item) {
item.quantity -= 1;
if (item.quantity <= 0) {
this.items.remove(item);
}
}
}
}
Here, removeItem is a class-property whose value is an arrow-function. Because of the arrow-function, it binds to the lexical this, which is the instance of the Cart.