MobX 更新装饰数组 属性 内的装饰对象不会发出反应

MobX Updating a decorated object inside a decorated array property doesn't emit reaction

我为我正在处理的工资率字段编写了一个 React 原型,现在我正在尝试将状态提升到域存储。现在,我只是想测试控制台中的反应,但出于某种原因,当使用操作更改该商店的可观察数组的字段时,反应不起作用。

代码

我有以下内容:

数据对象

class PayRate {
  /**
   * @param {number} taskId The id of the task. (-1 for all)
   * @param {Date} effectiveDate The date the payrate goes in effect.
   * @param {number} rate The rate of pay.
   */
  constructor(taskId, effectiveDate, rate) {
    this.TaskId = taskId || -1;
    this.EffectiveDate = effectiveDate ? new Date(effectiveDate) : new Date();
    this.Rate = rate || 0.00;
    this.OriginalObject = Object.assign({}, this);
  }

  /**
   * Gets a readable version of the effective date.
   * @returns {string} A -m/dd/yyyy representation of the effective date.
   */
  GetReadableDate() {
    return this.EffectiveDate.toLocaleDateString("en-US");
  }
  /**
   * Gets a one line description of the pay rate.
   * @returns {string} A string in the form of (date) - payrate.
   */
  GetDescription() {
    return `(${this.GetReadableDate()}) - $${this.Rate.toFixed(2)}`;
  }
  /**
   * Gets a one line description of the pay rate.
   * Does the exact same as GetDescription(), but is overload of Object.prototype.toString, which allows for stringification of Objects
   * @returns {string} A string in the form of (date) - payrate.
   */
  toString() {
    return `(${this.GetReadableDate()}) - $${this.Rate.toFixed(2)}`;
  }
  /**
   * Tells whether a pay rate was changed or not.
   * @returns {boolean} A boolean saying whether or not the pay rate was changed.
   */
  IsChanged() {
    if (this.EffectiveDate.getTime() !== this.OriginalObject.EffectiveDate.getTime()) {
      return true;
    }
    if (this.Rate != this.OriginalObject.Rate) {
      return true;
    }
    if (this._deleted) {
      return true;
    }
    return false;
  }
  /**
   * Reverts the changes back to the original.
   */
  RevertChanges() {
    Object.assign(this, this.OriginalObject);
  }
}

// mobx decorations
mobx.decorate(PayRate, {
  TaskId : mobx.observable,
  EffectiveDate : mobx.observable,
  Rate : mobx.observable,
})

域名存储

class PayRatesStore { 
    constructor() { 
        this.payRates = [];

        this.payRateIndex = -1;

        this._dateString = '';

        this.payRateIndicesToDelete = [];

        mobx.autorun(() => {
            console.log(this.payRates)
            console.log(this.currentPayRate)
        })
    }

    // getters
    get currentPayRate() { 
        if ((this.payRates) && (this.payRates.length)) {
            return this.payRates[this.payRateIndex];
        }
        return new PayRate();
    }

    get dateString() { 
        if (!this._dateString) { 
            if (this.currentPayRate) { 
                return this.currentPayRate.GetReadableDate()
            }
            return "";
        }
        return this._dateString;
    }

    set dateString(str) { 
        this._dateString = str;
    }

    updateCurrentPayRateDate(dateString) { 
        // update _dateString
        this._dateString = dateString

        this.payRates[this.payRateIndex].EffectiveDate = new Date(dateString)
    }
}

mobx.decorate(PayRatesStore, {
    payRates : mobx.observable,
    payRateIndex : mobx.observable,
    _dateString : mobx.observable,
    payRateIndicesToDelete : mobx.observable,
    currentPayRate : mobx.computed,
    dateString : mobx.computed,
    updateCurrentPayRateDate : mobx.action.bound
})

设置 PayRatesStore 会引起我们预期的反应:

let payRate = new PayRate(1, "03/25/2019", 15.5),
  payRates = [ payRate ]
// create PayRatesStore
let payRatesStore = new PayRatesStore()
console.log("Passing data to pay rates store....")
  payRatesStore.payRates = payRates
  payRatesStore.payRateIndex = 0

导致以下 console.logged:

然而,当我尝试时:

payRatesStore.updateCurrentPayRateDate('4/1/2019')

没有任何反应; // MobX 没有反应!!

我不知道我能做些什么来让 MobX 对此做出反应,因为它是从 React 组件中提取出来的。

看来您误解了自动运行的工作原理。 autorun 订阅函数中引用的变量值的变化。

发生了什么

在这里,您的自动运行函数正在观察 payRatescurrentPayRate

第一次,你同时修改了payRatescurrentPayRate(因为你改变了payRateIndex,它更新了计算的属性currentPayRate).

-> autorun 反应。

第二次,你修改payRates数组中的一个元素属性,不是this.payRates本身的值,还是同一个数组.所以,payRates没有变,currentPayRate.

也没有变

-> autorun 没有反应。

关于自动运行的更多信息

Autorun 不会订阅 "nested" 数组元素。更多详情,您可以阅读:Watch for nested object/array changes