MobX, украшающий класс, заставляет функцию вызывать TypeError - PullRequest
0 голосов
/ 25 апреля 2019

У меня есть два класса данных (бизнес-логика, которые я не писал), которые я пытаюсь использовать в магазине.Я исправил проблемы в этом магазине, украсив их.Они определены как:

// data classes; // these would be in separate file. 
class PayRate {
  /**
   * @param {number} storeId The store id of the pay rate. (-1 for all)
   * @param {number} empId The id of the employee. (-1 for all)
   * @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(storeId, empId, taskId, effectiveDate, rate) {
    this.StoreId = storeId || -1;
    this.EmpId = empId || -1;
    this.TaskId = taskId || -1;
    this.EffectiveDate = effectiveDate ? new Date(effectiveDate) : new Date();
    this.Rate = rate || 0.00;
    this.OriginalObject = $.extend(true, {}, 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() {
    $.extend(true, this, this.OriginalObject);
  }
}

mobx.decorate(PayRate, {
  StoreId : mobx.observable,
  EmpId : mobx.observable,
  TaskId : mobx.observable,
  EffectiveDate : mobx.observable,
  Rate : mobx.observable,
})

class TaskObject {
  /**
   * @param {Task} task The task that is being kept track of.
   * @param {PermissionLink[]} permissionLinks A list of permission links that are being kept track of.
   * @param {PayRate[]} payrates A list of pay rates that are being kept track of.
   */
  constructor(task, permissionLinks = [], payrates = []) {
    this.Model = $.extend(true, {}, task);
    this.Model.Type = 25;
    this.PermissionLinks = $.extend(true, [], permissionLinks);
    this.Payrates = $.extend(true, [], payrates);
    this.OriginalObject = $.extend(true, {}, this);
  }
  /**
   * Gives the dirty status of the task object.
   * @returns {boolean} Tells whether or not the TaskObject has been changed.
   */
  IsChanged() {
    if (this.Model.Id == -1) {
      return true;
    }
    if (this.Model.Name != this.OriginalObject.Model.Name) {
      return true;
    }
    if (this.Model.GroupName != this.OriginalObject.Model.GroupName) {
      return true;
    }
    if (this.Model.DescStr != this.OriginalObject.Model.DescStr) {
      return true;
    }
    if (this.Model.IsActive != this.OriginalObject.Model.IsActive) {
      return true;
    }
    if (this.PermissionLinks.length != this.OriginalObject.PermissionLinks.length) {
      return true;
    }
    for (let i = 0; i < this.PermissionLinks.length; i++) {
      const element = this.PermissionLinks[i];
      const compElement = this.OriginalObject.PermissionLinks[i];
      if (JSON.stringify(element) !== JSON.stringify(compElement)) {
        return true;
      }
    }
    for (let i = 0; i < this.Payrates.length; i++) {
      const payrate = this.Payrates[i];
      if (payrate.IsChanged()) {
        return true;
      }
    }
    return false
  }
  /**
   * Reverts the changes that are on the task object.
   * @returns {TaskObject} The TaskObject with its changes discarded.
   */
  RevertChanges() {
    this.Model = $.extend(true, {}, this.OriginalObject.Model);
    this.PermissionLinks = $.extend(true, [], this.OriginalObject.PermissionLinks);
    for (let i = 0; i < this.Payrates.length; i++) {
      this.Payrates[i].RevertChanges()
    }
    return this;
  }

  /**
   * This is here for debugging purposes (i.e. with data stores that use it) and may be overwritten with business logic at any time
   */
  toString() { 
    return JSON.stringify(this, null, '\t')
  }
}

// marking all the properties of TaskObject observable
mobx.decorate(TaskObject, {
  Model : mobx.observable,
  PermissionLinks : mobx.observable,
  Payrates : mobx.observable,
  RevertChanges : mobx.action,
  IsChanged : mobx.computed
})

Теперь, выполнение new PayRate().IsChanged() работает как положено, но new TaskObject.IsChanged() приводит к:

Uncaught TypeError: Cannot read property 'call' of undefined
    at e.computeValue (mobx.umd.min.js:1)
    at e.get (mobx.umd.min.js:1)
    at e.read (mobx.umd.min.js:1)
    at TaskObject.get (mobx.umd.min.js:1)
    at pen.js:163
e.computeValue @ mobx.umd.min.js:1
e.get @ mobx.umd.min.js:1
e.read @ mobx.umd.min.js:1
get @ mobx.umd.min.js:1
(anonymous) @ pen.js:163

Вот демо

Почему это происходит и как я могу это исправить?

1 Ответ

0 голосов
/ 25 апреля 2019

Вы объявляете IsChanged как функцию, но оформляете ее как вычисленное свойство , а затем вызываете ее как функцию. Если вы хотите, чтобы это было вычисляемое свойство, вам необходимо:

  • преобразовать его в геттер: IsChanged() -> get IsChanged()
  • назовите это без скобок: TaskObject.IsChanged
...