获取数据作为对 MobX 中可观察数组变化的反应
Fetching data as reaction to observable array change in MobX
假设我们有一个可观察的主对象数组,以及关于该数组的可观察数据(例如,假设我们有 selectedReports
和 reportParameters
)。现在假设我们发出操作以将 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
}
你真的打电话给 fetchAllReportParameters
吗?如果不这样做,将永远不会产生反应。您可能更喜欢从构造函数创建 reaction
,假设您始终希望它是 运行。一个例子:
class SomeStore {
constructor() {
this.disposeReportsReaction = reaction(
() => this.selectedReports.slice(),
reports => {
// ...
}
)
}
}
每当您完成反应时,请致电 storeInstanceName.disposeReaction()
。
请注意,我在这里使用了 .slice()
。这是因为如果您只是传递数组引用,则永远不会调用反应。请参阅 reaction
docs:您必须以某种方式实际使用该值。
您还需要稍微调整一下异步代码。这个:
async (reports) => {
await reports.forEach((report) => {
// ...
})
}
不会如你所愿,因为forEach
returns undefined
。即使您将 async
关键字转移到 forEach
回调,所有 API 请求也会快速连续发送。考虑使用类似这样的方法,具体取决于您是否要在发送下一个请求之前等待前面的请求:
try {
for (const report of reports) {
await this.fetchReportParameters(report.id)
}
} catch (e) {
// handle error
}
这并不总是正确的答案:有时可以快速连续发送一堆请求(也许特别是如果它是小批量的,and/or 在 HTTP/2 的上下文中) .如果您不介意,您可以使用:
reports => {
// ...
reports.forEach(report => this.fetchReportParameters(report.id))
}
假设我们有一个可观察的主对象数组,以及关于该数组的可观察数据(例如,假设我们有 selectedReports
和 reportParameters
)。现在假设我们发出操作以将 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
}
你真的打电话给 fetchAllReportParameters
吗?如果不这样做,将永远不会产生反应。您可能更喜欢从构造函数创建 reaction
,假设您始终希望它是 运行。一个例子:
class SomeStore {
constructor() {
this.disposeReportsReaction = reaction(
() => this.selectedReports.slice(),
reports => {
// ...
}
)
}
}
每当您完成反应时,请致电 storeInstanceName.disposeReaction()
。
请注意,我在这里使用了 .slice()
。这是因为如果您只是传递数组引用,则永远不会调用反应。请参阅 reaction
docs:您必须以某种方式实际使用该值。
您还需要稍微调整一下异步代码。这个:
async (reports) => {
await reports.forEach((report) => {
// ...
})
}
不会如你所愿,因为forEach
returns undefined
。即使您将 async
关键字转移到 forEach
回调,所有 API 请求也会快速连续发送。考虑使用类似这样的方法,具体取决于您是否要在发送下一个请求之前等待前面的请求:
try {
for (const report of reports) {
await this.fetchReportParameters(report.id)
}
} catch (e) {
// handle error
}
这并不总是正确的答案:有时可以快速连续发送一堆请求(也许特别是如果它是小批量的,and/or 在 HTTP/2 的上下文中) .如果您不介意,您可以使用:
reports => {
// ...
reports.forEach(report => this.fetchReportParameters(report.id))
}