我正在使用Redux和ImmutableJS。在我的SPA(非常复杂的管理系统)中,用户经常将大量数据加载到存储中(许多表的数千行)。在打开几个页面并且商店中的数据太多之后,应用程序变得非常慢,因为ImmutableJS商店甚至可以包含数百万个条目。
我怎样才能删除"来自商店的东西,以便数据不会减慢应用程序的速度?我知道这会违背其主要原则,但你怎么解决呢?
使用例如jQuery的通用网站,这将非常简单。每次刷新页面时,所有不必要的内容都会被垃圾回收。因此,一个页面的2-3,000个条目就可以了,但是当打开一个新页面时,reducer会加载新数据,但旧的数据仍然被引用。
当然,我并不想强迫用户重新加载页面。
答案 0 :(得分:4)
Redux中的变异状态几乎总是真正bad idea,因为它是库的一种先决条件。我的第一个问题是三重检查你是否因为内存膨胀而导致内存问题,而不是由于不必要的重新渲染或由于不必要的计算。我的意思是,如果你在同一个地方保存大量数据,请确保你没有做任何导致React不必要地重新渲染事物或筛选过多数据的东西。
您可以通过司法使用reselect库或使用其他类型的记忆来解决该问题,这些记忆将以避免不必要的重新计算的方式从您的Reducer中检索数据。同样,请确保在更改单行时,整个列表中不是unnecessarily re-rendering every item。
如果你真的需要沿着这条路走下去,那么你必须保持旧页面的数据“活着”,因为只有JavaScript才会收集不再被引用的内容。
Vanilla Redux并没有坚持以前的状态。它所做的只是将当前状态保持在let
变量中,然后在从调度操作到根减速器获取新状态后更改其值(参见source code)。
所以,我会确保我没有使用像persists previous state这样的redux dev工具。
然后在reducer中,创建一个不以任何方式使用先前数据的新对象,而是返回一个包含新数据的新对象:
const data = (state, action) => {
switch (action.type) {
case 'RETRIEVE_DATA_SUCCESS':
return action.payload;
default:
return state
}
}
我建议您阅读Chrome的内存分析工具here,以确保其正常运行。
答案 1 :(得分:3)
我建议不要将整个数据保存在商店中,以便将其指针保存到内存解决方案(localstorage,REDIS等)。我会使用PouncDB并仅将_rev
版本号存储在我的商店中。
答案 2 :(得分:1)
关于Immutablejs保持旧数据“活着”的前一篇文章是错误的......好吧,从某种意义上说它正在被描述。 Immutablejs使用结构共享,这意味着它只会创建一个新节点和它的子节点,同时与旧数据共享其余的trie。如果您查看下面的图像,您会看到右侧的绿色和黄色点是新数据与旧数据共享其结构。
旧数据部分(右侧蓝点) 可用于垃圾回收,只要您不在应用程序的其他位置继续引用它 。如果您想为您的应用添加时间旅行功能,那么保持参考是最有益的。
如果每个惯用的Redux都深深地克隆了每个对象,那么在没有immutablejs的结构共享的情况下,你会遇到更大的内存问题。所以没有看到一些代码,我怀疑这里的问题是不可改变的。
您是否偶然使用toJS()
?如果你是,这是一项昂贵的操作,除非绝对必要,否则应该避免。它还会断开不可变实例的连接,您将失去结构共享的所有好处。这是我见过的一个常见错误。您可以在不调用toJS()
的情况下访问这些值
const immVal = List([1,2,3])
console.log([...immVal.values()])
Lee Byron's talk (creator of immutablejs)结构共享@ 23:40和垃圾收集@ 24:50
答案 3 :(得分:0)
由于我看到有人推荐了PouchDB,我希望您对reduxdb进行试用,我们已经在生产中使用了近一年,并且没有发现任何性能问题。