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

  • MobX Quick Start Guide
  • Pavan Podila Michel Weststrate
  • 530字
  • 2021-08-05 10:34:25

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.

主站蜘蛛池模板: 韶山市| 夏河县| 金沙县| 抚顺县| 游戏| 南部县| 秭归县| 巴林右旗| 巴马| 连城县| 舒兰市| 靖安县| 通榆县| 新竹县| 遂平县| 遂宁市| 闸北区| 垫江县| 河北省| 儋州市| 阜新| 银川市| 乐亭县| 成武县| 宾川县| 疏勒县| 江源县| 凉城县| 司法| 天等县| 九寨沟县| 南溪县| 泸西县| 华蓥市| 泰宁县| 虹口区| 喀喇| 大英县| 罗田县| 二连浩特市| 东山县|