Redux状态树是否应表示UI中数据的组织方式?

Sha*_*ere 5 javascript reactjs redux

情况

我有一个React/Redux应用程序在地图上显示标记,并根据当前缩放级别的近距离将它们分组到群集中(类似于此示例 - 我的应用程序与此示例略有不同,因为地图上的群集将显示来自其子标记的特定数据,而不仅仅是儿童标记的总数).

我预计会经常添加新标记,应用程序会更新以实时显示新标记.

React组件结构如下所示:

<Map>
  <Cluster markerIds=[...] />
  ...
</Map>
Run Code Online (Sandbox Code Playgroud)

因此,每次a)将新标记添加到地图时,地图会重新渲染相应的聚类,以及b)地图的缩放级别更改.

我正在尝试确定在Redux状态树中组织此数据的最佳方法.

选项1:简单方法

一种选择是保持状态树非常简单,并让UI根据需要处理所有集群逻辑:

{
  markers: {
    1: { name: 'Bob', location: [-40.08, 37.62] },
    2: { name: 'Steve', location: [51.08, -25.62] },
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我以这种方式组织状态,则UI必须遍历每个标记并在每次缩放级别更改时重新计算可见群集.有了大量的标记,这可能会导致大量的重新计算,我预计用户在使用此应用程序时会进行大量的放大和缩小.

选项2:为每个缩放级别存储群集组

另一种选择是将群集组织保持在每个缩放级别的状态树中(例如1到19):

{
  markers: {
    1: { name: 'Bob', location: [-40.08, 37.62] },
    2: { name: 'Steve', location: [51.08, -25.62] },
    ...
  },
  clustersByZoomLevel: {
    1: {
      clusters: [
        {
          clusterLocation: [22.59, -21.54],
          markers: [2, 11, 4]
        },
        ...
      ]
    },
    ...2-19: {...}
  }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,只有在将新标记添加到地图时才会进行群集计算,并且只会在新标记上运行,而不是在整个集合上运行.放大或缩小不需要重新计算,因为群集组织已经存储在该州.

这个问题

那么,哪个选项更有意义呢?

一方面,我被迫保持简单并避免过早优化(即选择方案1).

另一方面,我可以看到选项1很容易导致大量的重新计算频繁发生.选项2提供了一个状态树,可以更直接地转换为我的React组件结构.

你会建议哪个选项,为什么?他们不考虑的其他方法可能会更好吗?

Nor*_*ard 4

从你问的情况来看,两者都是可行的。

由于您的具体问题的性质(取决于规模),我想说缓存层是完全可行的(只要纯数据集保留在那里)。

就我的团队运作的一组抽象思想而言:如果可以简单地导出它,则在馈送到 的变压器中进行connect( transform, bind )( Widget );

如果它不能被简单地导出,那么缓存它就很有意义。

一个很好的例子是,您可能有 8000 个原始产品结果,然后过滤滑块,对结果中的各种数据进行操作。
您将需要保留一个filteredResults 列表,这样您就不必不断地重新计算。

不过,更改视图的页码不需要重新运行所有这些昂贵的过滤操作(即:在转换中),而只需选择从所有已过滤结果的列表中切片的视图子集即可。

这比你所要求的更进一步,但我的另一项建议是“按 UI 组织”:小心地将公共数据从树的“页面”或“api”特定分支中旋转出来,并将它们移动到一个常见的地方,如果它们确实是常见的东西的话。

必须在两个不同的地方改变一个对象才能保持彼此同步将是痛苦的。

{
  searchPage: { user },
  landingPage: { user },
  checkoutPage: { user }
}
Run Code Online (Sandbox Code Playgroud)

要匹配UI将会是非常痛苦的。

所以......转换你可以合理导出的内容,缓存你不能导出的内容,旋转常见的内容以更接近根。