获取数据作为对MobX中可观察到的数组更改的反应

时间:2019-07-12 19:08:38

标签: mobx

假设我们有一个可观察的主对象数组,以及有关该数组的可观察数据(例如,假设我们有selectedReportsreportParameters)。现在,假设我们发出动作以将report添加到数组或从该数组中删除report。我们该如何执行动作以获取reportParameters的数据,作为反应?

到目前为止,我的尝试无效,看起来像这样:

// report parameters stuff
async fetchAllReportParameters() {
    reaction(
        () => this.selectedReports,
        async (reports) => {
            // reset the report parameters
            this.reportParameters = {}
            // fetch the parameters for all the reports
            await reports
                .forEach((report) => { 
                this.fetchReportParameters(report.Id)
            })
        }
    )
}
/**
 * fetches report parameters for a reportId
 * @param {number} reportId 
 */
fetchReportParameters = (reportId) => {
    this.reportParameters[reportId] = []

    const onSuccess = (reportParameters) => {
        this.reportParameters[reportId] = reportParameters
    }

    this.api.GetReportParameters(reportId)
        .then(onSuccess, this.fetchReportParametersError)


}

fetchReportParametersError = (error) => { 
    // TODO: output some error here
}

1 个答案:

答案 0 :(得分:1)

您真的打电话过fetchAllReportParameters吗?如果您不这样做,将永远不会创建反应。相反,您可能想从构造函数创建reaction,假设您始终希望运行它。一个例子:

class SomeStore {
  constructor() {
    this.disposeReportsReaction = reaction(
      () => this.selectedReports.slice(),
      reports => {
        // ...
      }
    )
  }
}

反应完成后,请致电storeInstanceName.disposeReaction()

请注意,我在这里使用了.slice()。这是因为,如果仅传递数组引用,则永远不会调用该反应。请参见reaction docs:您必须以某种方式实际使用该值。

您还需要稍微调整一下异步代码。这个:

  async (reports) => {
    await reports.forEach((report) => {
      // ... 
    })
  }

不会做您希望的事情,因为forEach返回undefined。即使将async关键字移至forEach回调,所有API请求也将快速连续发送。考虑使用类似的方法,具体取决于您是否要在发送下一个请求之前等待上一个请求:

try {
  for (const report of reports) {
    await this.fetchReportParameters(report.id)
  }
} catch (e) {
  // handle error
}

这并不总是正确的答案:有时可以快速连续发送一堆请求(也许特别是如果是一小批,和/或在HTTP / 2的情况下)。如果可以的话,您可以使用:

  reports => {
    // ...
    reports.forEach(report => this.fetchReportParameters(report.id))
  }