在redux存储中处理“selected”项目的正确方法

14

我希望听取关于如何结构化Redux Store的意见,特别是需要同时保留项目列表和选定项目的情况。例如,给定一个包含项目列表和选定项目详细信息的页面,用户应该能够从列表中选择一个项目。当选择了一个项目后,它的详细信息应该被加载。当选定的项目被更新时,详细信息和列表中的项目也应该被更新(例如,如果项目名称已更改,则在列表中也应该可见)。所有数据都应该从后端获取,并且列表中的项目模型与选定项目模型不同。列表中的项目具有较少的属性/详情,而选定项目则具有有关数据的更多信息。

您认为在这种情况下最佳的Redux Store结构应该是什么?我已经尝试过搜索示例,但通常所有示例都认为项目列表中的项目和选定项目相同,因此没有必要为详细项目保留单独的对象。

我尝试了简单的方法:只在存储中保留项目列表和选定项目:

storeExample = {
    items: {
        1: item1,
        2: item2,
        3: item3
    }
    selectedItem: detailedItem1
};

有更好的组织商店的方式吗?希望我的问题表达清楚,因为有点难以解释我的担忧。会很感激任何“实时”的例子。

4个回答

11

如果您使用 itemN 作为键,访问您选择的任何 item 就变得更加容易和快速。

storeExample = {
  items: {
      item1: {...},
      item2: {...},
      itemN: {...},
  },
  selectedItem: itemN,
}

然后,您可以通过 this.props.items[this.props.selectedItem] 轻松地在组件中访问 selectedItem

所有数据应该从后端获取,并且列表中的项模型与所选项模型不同。列表中的项具有较少的属性/详细信息。所选项具有有关数据的更多信息。

这样做没有太多理由。只需将所有详细信息存储在存储库中,它将节省API调用并使从存储库获取数据更快。


item1与detailedItem1不同。ItemN包含列表中的一些最小数据,而detailedItemN则包含有关该项的所有详细信息。 - Ruben Nagoga
1
因此,我的回答末尾有评论。没有太多理由这样做。您可以首先加载“item”,然后在使用其详细信息时逐步填充它们,但保持它们在同一位置。这使商店更易于导航和理解,并最终节省了额外的API调用。 - jacques mouette
我强烈反对在React Native中使用你所说的结构并插入像redux-persist这样的中间件,如果应用程序正在处理列表中的大对象,则应用程序会崩溃,而redux-persist永远无法重新加载。 - Giacomo Cerquone
但是如果项目列表被重新获取并更改了呢?ItemN 将会指向意外的东西。 - Raymond Pang

2

如果一开始就加载带有大量数据的detailedItem,而你又有很长的item列表,我可以理解为什么不会这样做。我使用的解决方案基本上和你自己建议的一样。


1

这很好。

请记住,redux 中重复使用数据引用是可以的 - 存储库可以有大量对相同对象的引用。因此,您可以在 items 对象中愉快地使用完整的 detailedItem,这将使选择更容易,因为您只需将要选择的项目传递给操作创建者即可。

通常拥有简单的 reducer 是一个好习惯,因为它们可能是非常奇怪的 bug 的源头,所以这听起来是一种不错的方法。


你是什么意思说“所以你可以愉快地在items对象中使用完整的detailedItem”? - Ruben Nagoga
你说你的 items 数组只包含有关对象的有限信息,但由于你只涉及引用,始终使用完整详细的对象可能更简单。 - Duncan Thacker

0
理论上来说,这应该是正确的方法,但如果你的ajax有缓存,这样做并不能提高太多性能。

// in redux store
storeExample = {
  items: {
    1: item1,
    2: item2,
    3: item3
  },
  selectedIndex: 0,
  detailedItems: [],
}

// react use example 

export default connect(({
  itemds,
  selectedIndex,
  detailedItems,
}) => {
  return {
    items,
    selectedIndex,
    selectedItem: detailedItems[selectedIndex],
    detailedItems,
  }
})(({
  items,
  selectedIndex,
  selectedItem,
  dispatch
}) => (<div>
  <span>selected: {selectedItem?selectedItem.name:'NONE'}</span>
  <select value={selectedIndex} onChange={(e)=>{
    const i = e.tartet.value
    dispatch(updateIndex(i))
    if(i!=0 && !detailedItems[i]){
    dispatch(loadDetail(i))
    }
  })}>
    <option value={0}>-choose-<option>
    {items.map((item,i)=><option key={i} value={i}>{item.name}<option>)}    
  </select>
</div>))

1.列表有顺序,但对象没有

2.一旦缓存到详细列表中,最好的方法是通过函数从详细列表进行索引,快速、无冗余

3.对详细列表项的更改将直接应用

4.如果您的列表索引以0开始,则可以将selectedIndex赋值为-1(大多数情况下列表索引以0开头)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接