官术网_书友最值得收藏!

reaction()

reaction() is yet another kind of reaction in MobX. Yes, the choice of the API name was intentional. reaction() is similar to autorun() but waits for a change in the observables before executing the effect-function. reaction() in fact takes two arguments, which are as follows:

reaction(tracker-function, effect-function): disposer-function

tracker-function: () => data, effect-function: (data) => {}

tracker-function is where all the observables are tracked. Any time the tracked observables change, it will re-execute. It is supposed to return a value that is used to compare it to the previous run of tracker-function. If these return-values differ, the effect-function is executed.

By breaking up the activity of a reaction into a change-detecting function (tracker function) and the effect function, reaction() gives us more fine-grained control over when a side-effect should be caused. It is no longer just dependent on the observables it is tracking inside the tracker function. Instead, it now depends on the data returned by the tracker function. The effect function receives this data in its input. Any observables used in the effect function are not tracked.

Just like autorun(), you also get a disposer function as the return-value of reaction(). This can be used to cancel the side-effect anytime you want.

We can put this into practice with an example. Let's say you want to be notified anytime an item in your Cart changes its price. After all, you don't want to purchase something that suddenly shoots up in price. At the same time, you don't want to miss out on a great deal as well. So, getting a notification when the price changes is a useful thing to have. We can implement this by using reaction(), as shown here:

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

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

cancelPriceTracker = null;

trackPriceChangeForItem(name) {
if (this.cancelPriceTracker) {
this.cancelPriceTracker();
}

// 1. Reaction to track price changes
this.cancelPriceTracker = reaction(
() => {
const item = this.items.find(x => x.name === name);
return item ? item.price : null;
},
price => {
console.log(`Price changed for ${name}: ${price !==
null ? price : 0}`);
},
);
}

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

@action
changePrice(name, price) {
const item = this.items.find(x => x.name === name);
if (item) {
item.price = price;
}
}
}

const cart = new Cart();

cart.addItem('Shoes', 20);

// 2. Now track price for "Shoes"
cart.trackPriceChangeForItem('Shoes');

// 3. Change the price
cart.changePrice('Shoes', 100);
cart.changePrice('Shoes', 50);

// Prints:
// Price changed for Shoes: 100
// Price changed for Shoes: 50

In the preceding snippet, we are setting up a price tracker in comment 1, as a reaction to track price changes. Notice that it takes two functions as inputs. The first function (tracker-function) finds the item with the given name and returns its price as the output of the tracker function. Any time it changes, the corresponding effect function is executed.

The console logs also print only when the price changes. This is exactly the behavior we wanted and achieved through a reaction(). Now that you are notified of the price changes, you can make better buying decisions.

主站蜘蛛池模板: 山阴县| 大方县| 湘潭县| 和平县| 永康市| 黄陵县| 高州市| 贵港市| 惠州市| 绥化市| 犍为县| 瑞安市| 胶南市| 锡林郭勒盟| 济源市| 镇宁| 黄山市| 泸定县| 修武县| 开平市| 内乡县| 霍城县| 东源县| 崇文区| 田林县| 周宁县| 通辽市| 同仁县| 包头市| 乌兰察布市| 曲麻莱县| 无棣县| 定安县| 晋城| 兰州市| 台前县| 桂林市| 景泰县| 固原市| 新源县| 建始县|