Redux 状态树是否应该表示数据在 UI 中的组织方式?
Should a Redux state tree represent how data is organized in the UI?
情况
我有一个 React/Redux 应用程序可以在地图上显示标记,并在给定当前缩放级别的情况下根据它们的接近程度将它们分组到集群中(similar to this example - 我的应用程序与此示例略有不同地图上的集群将显示来自其子标记的特定数据,而不仅仅是子标记的总数)。
我预计会经常添加新标记,应用会更新以实时显示新标记。
React 组件结构如下所示:
<Map>
<Cluster markerIds=[...] />
...
</Map>
因此地图会在每次 a) 新标记被添加到地图时重新渲染适当的集群,并且 b)地图的缩放级别发生变化。
我正在尝试确定在 Redux 状态树中组织这些数据的最佳方式。
选项 1:简单方法
一个选择是保持状态树非常简单,让 UI 根据需要处理所有集群逻辑:
{
markers: {
1: { name: 'Bob', location: [-40.08, 37.62] },
2: { name: 'Steve', location: [51.08, -25.62] },
...
}
}
如果我以这种方式组织状态,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: {...}
}
}
在这种情况下,聚类计算只会在新标记添加到地图时发生,并且只会 运行 在新标记上,而不是在整个集上。放大或缩小不需要重新计算,因为集群组织已经存储在状态中。
问题
那么,哪个选项更有意义?
一方面,我不得不保持简单并避免过早优化(即选择选项 1)。
另一方面,我可以看到选项 1 很容易导致非常频繁地发生大量重新计算。而选项2提供了一个状态树,可以更直接地转化为我的React组件结构。
您会建议哪个选项,为什么?他们的其他方法我没有考虑可能会更好吗?
根据你的要求,两者都是可行的。
由于您确切问题的性质(取决于规模),我会说缓存层是完全可行的(只要纯数据集保留在那里)。
就我的团队运作的一组抽象思想而言:
如果可以简单地导出,请在馈送到 connect( transform, bind )( Widget );
.
的变压器中进行
如果不能简单地导出它,那么缓存它就很有意义了。
这方面的一个很好的例子是您可能有 8000 个原始产品结果,然后是筛选滑块,它对结果中的各种数据进行操作。
您将要保留一个 filteredResults 列表,这样您就不必不断地重新计算它。
不过,更改视图的页码不应该需要重新运行所有那些昂贵的过滤操作(即:在转换中),而只是选择从所有已经-筛选结果。
这比您的要求更进一步,但我的另一个建议是 "organizing by UI":请小心将公共数据从 "page" 或 "api" 特定树的分支,如果它们确实是普通的东西,就把它们移到一个普通的地方。
必须在两个不同的地方改变一个对象,以保持彼此同步会很痛苦。
{
searchPage: { user },
landingPage: { user },
checkoutPage: { user }
}
匹配UI会很痛苦
所以...转换您可以理智派生的内容,缓存您不能理智派生的内容,旋转常见的内容以更接近根。
情况
我有一个 React/Redux 应用程序可以在地图上显示标记,并在给定当前缩放级别的情况下根据它们的接近程度将它们分组到集群中(similar to this example - 我的应用程序与此示例略有不同地图上的集群将显示来自其子标记的特定数据,而不仅仅是子标记的总数)。
我预计会经常添加新标记,应用会更新以实时显示新标记。
React 组件结构如下所示:
<Map>
<Cluster markerIds=[...] />
...
</Map>
因此地图会在每次 a) 新标记被添加到地图时重新渲染适当的集群,并且 b)地图的缩放级别发生变化。
我正在尝试确定在 Redux 状态树中组织这些数据的最佳方式。
选项 1:简单方法
一个选择是保持状态树非常简单,让 UI 根据需要处理所有集群逻辑:
{
markers: {
1: { name: 'Bob', location: [-40.08, 37.62] },
2: { name: 'Steve', location: [51.08, -25.62] },
...
}
}
如果我以这种方式组织状态,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: {...}
}
}
在这种情况下,聚类计算只会在新标记添加到地图时发生,并且只会 运行 在新标记上,而不是在整个集上。放大或缩小不需要重新计算,因为集群组织已经存储在状态中。
问题
那么,哪个选项更有意义?
一方面,我不得不保持简单并避免过早优化(即选择选项 1)。
另一方面,我可以看到选项 1 很容易导致非常频繁地发生大量重新计算。而选项2提供了一个状态树,可以更直接地转化为我的React组件结构。
您会建议哪个选项,为什么?他们的其他方法我没有考虑可能会更好吗?
根据你的要求,两者都是可行的。
由于您确切问题的性质(取决于规模),我会说缓存层是完全可行的(只要纯数据集保留在那里)。
就我的团队运作的一组抽象思想而言:
如果可以简单地导出,请在馈送到 connect( transform, bind )( Widget );
.
如果不能简单地导出它,那么缓存它就很有意义了。
这方面的一个很好的例子是您可能有 8000 个原始产品结果,然后是筛选滑块,它对结果中的各种数据进行操作。
您将要保留一个 filteredResults 列表,这样您就不必不断地重新计算它。
不过,更改视图的页码不应该需要重新运行所有那些昂贵的过滤操作(即:在转换中),而只是选择从所有已经-筛选结果。
这比您的要求更进一步,但我的另一个建议是 "organizing by UI":请小心将公共数据从 "page" 或 "api" 特定树的分支,如果它们确实是普通的东西,就把它们移到一个普通的地方。
必须在两个不同的地方改变一个对象,以保持彼此同步会很痛苦。
{
searchPage: { user },
landingPage: { user },
checkoutPage: { user }
}
匹配UI会很痛苦
所以...转换您可以理智派生的内容,缓存您不能理智派生的内容,旋转常见的内容以更接近根。