最近,我一直在研究一个非常大的应用程序,使用React + Redux和Reselect来记忆数据并防止不必要的重新渲染,我遇到了一个我似乎无法解决的特定问题。
在Redux状态下,我存储了大量数据作为id索引的对象。这些对象都有一个属性(我们称之为gps),它使用实时gps坐标进行更新。
此数据以两种方式使用。第一个是在地图上,GPS数据是相关的。第二个是UI,其中GPS数据不相关。每当在任何对象上更新GPS数据时,该对象将在Redux存储中流入并替换,Redux存储在选择器中更新该对象的引用。
Redux Store示例:
data: {
dogs: {
1: {id: 1, name: "name1", gps: [123, 234]},
2: {id: 2, name: "name2", gps: [123, 234]},
3: {id: 3, name: "name3", gps: [123, 234]},
4: {id: 4, name: "name4", gps: [123, 234]}
}
}
例如,state.dogs [1] .gps中的数据可能每秒更新3到5次。这可以在state.data.dogs中的任何对象中发生。
选择器编写如下:
const dogDataSelector = state => state.data.dogs;
const animalsSelector = createSelector(
dogDataSelector,
(dogs) => {
return Object.keys(dogs).map(id => {
return dogs[id];
})
}
)
现在,当我想要所有的狗时,这段代码可以正常工作,因为它们会更新,包括GPS。
我似乎无法弄清楚如何专门针对排除GPS更新的UI编写选择器。 100次中的99次,当狗更新时,它是GPS更新。 UI完全不关心GPS,但由于这一点,选择器向前发送新数据,导致UI重新呈现。
我知道如果狗的id或名称发生变化,可以编写一个只推送来自数据库的更改的新流,但这是一个我希望远离的解决方案,因为它会导致很多要在商店中多次存储的相同数据。
我尝试了以下内容:
如果有人需要更多信息或澄清,请不要犹豫。
更新:这是一个问题的主要原因之一是任何狗的任何GPS更新都会导致dogDataSelector返回一个新的引用。反过来,这将导致animalsSelector触发更新并返回一个新值。
答案 0 :(得分:1)
不可变数据更新的标准方法要求,如果更新嵌套字段,则应复制和更新树中的所有祖先。在您的示例中,对dog[3].gps
的更新需要gps
数组,dog[3]
,dogs
和data
的新引用。因此,使用此数据结构,对gps
字段的任何更新都必须在链中一直产生新引用,因此UI将看到新引用并假设它需要重新渲染。
一些可能的建议:
gps
字段,然后对前一个值进行某种浅等式检查,看看是否有非{{1实际上已经改变了字段,因此新的"狗条目减去gps
" object仅在其中一个字段不同时返回。答案 1 :(得分:0)
注意:这些评论中有详细信息
如果您不需要gps数据,那么您肯定可以将其剥离,reselect
会忽略它
类似的东西:
const dogDataSelector = state => state.data.dogs;
const animalsSelector = createSelector(
dogDataSelector,
(dogs) => {
return Object.keys(dogs).map(id => {
return dogs[id];
})
},
(dogsArray) => dogsArray.map(({id, name}) => ({id, name}))
)