关于“计算”的最佳实践,我有三个相关的问题。
TL; DR:我需要考虑一下自己以及和解开箱即用。
假设我将大量数据集加载到数据变量中:
data = asyncComputed( await fetch … return data )
然后我便有了方便计算的道具来格式化该数据:
@computed get timeseries() {
const data = this.data.get()
const timeseries = nest()
.key(d => d.geo)
.entries(data)
return timeseries
}
第三个方便的道具是根据时间序列计算的:
@computed get extentX() {
const timeseries = this.timeseries.get()
const extentX = extent(timeseries, d => d.time)
return extentX
}
是否存在在所有这些计算完成之前进行渲染的风险,或者MobX是否确保之前对此进行了协调?
是否有更好的方法来构造此代码,以避免链接已计算的道具?
比方说,当对象上的属性(id)发生更改并随后从同一事件链更新该对象时,将触发第一个异步操作:
variable = { id : “my-variable”, extent: undefined}
data = asyncComputed( await fetch api?id=variable.id )
=>计算范围=>结果为variable.extent = [200,400] 是否有可能引发无限循环的风险,或者像这样更新对象属性是否安全?
答案 0 :(得分:1)
这是我对此主题的看法。
@observer
时,它只是将渲染函数包装在autorun
(Proof)中从#1可以得出一个结论,如果我们有一个计算链,它们将像observable -> computed 1 -> computed 2
从#2可以说,为了产生副作用-此计算链必须以自动运行observable -> computed 1 -> computed 2 -> autorun
结尾
这已经使我们指向第3点。 @observer
是一个HOC,可将您的Component包裹起来并在需要重新呈现时进行控制。现在,这不受组件的控制。
所以回答您的问题:
computed
调用autorun
computed
的束缚是一种强大的方法,应该避免使用它,而应谨慎使用。 来自文档:
通过构成反应式计算,甚至可以将一个数据图自动转换为另一数据图,并以最少的补丁数保持此推导最新。这样可以轻松实现复杂的模式,例如映射减少,使用不可变共享数据的状态跟踪或横向数据加载。
答案 1 :(得分:0)
以我的经验,在其他“计算的”值之上构建MobX“计算的”值既简单又健壮,并且是将复杂的数据转换分解为逻辑和可测试的婴儿步骤的一种非常有效的方法。
使用一系列“计算”时,每个步骤都是在先前结果的基础上进行数据转换的,每个步骤都有一个名称。因此,每个步骤的结果就是一个可观察到的名称,您的应用可以查看或显示在屏幕上。这样可以轻松地分别编写,测试和调试每个步骤。
在运行时,您的顶级“计算”获得与简单“计算”相同的神奇效率和重新计算,因此实际上没有不利之处。我强烈推荐它。