假设我有一个api端点
/categories,它返回一个类别数组
[
{
id: '1'
name: 'category-1'
},
{
id: '2'
name: 'category-2'
}
...
]
Run Code Online (Sandbox Code Playgroud)
和端点,用于items/:categoryId返回返回项目数组的类别中的项目
[
{ id: '1', name: 'item-1' },
{ id: '2', name: 'item-2' }
...
]
Run Code Online (Sandbox Code Playgroud)
在UI上,我显示了一个类别列表,我可以展开这些类别并延迟加载项目列表.我希望能够扩展多个类别,并且需要能够添加,编辑和删除项目.
为这样的场景组织国家的最佳方式是什么?
目前我的州看起来像这样:
{
entities: {
categories: {
'1': {
id: '1'
name: 'category-1'
},
'2': {
id: '2'
name: 'category-2'
},
...
},
items: {
'1': {
id: '1'
name: 'item-1'
},
'2': {
id: '2'
name: 'item-2'
},
...
}
},
categories: {
ids: ['1', '2', ...],
isFetching: bool
error: null
},
itemsByCategory: {
'1': {
ids: ['1', '2',...]
isFetching: bool,
error: null
}
...
}
}
Run Code Online (Sandbox Code Playgroud)
在itemsByCategory键中是类别的ID,如果尚未加载给定类别的项目,则键不会存在itemsByCategory.
该解决方案有效,但有一些缺点.为了删除项目,我必须传递两个键(项目ID和类别ID)而不仅仅是项目ID(我也可以通过所有类别来查找项目,但它可能会变慢).
我也不满意检查是否加载了给定类别的项目.(首先我要检查是否定义了具有类别id的键
itemsByCategory),因此我的选择器变得有点复杂.
有没有更好的方法来塑造这种情况的状态?
对于需要传递类别 id 和项目 id 以便从类别中删除项目,我们无能为力。这是因为它们是相互联系的。
从您的特定用例中抽象出来,每次您想要更改两个逻辑实体之间的连接(建立新的或破坏现有的)时,您都必须以某种方式解决该连接。可以办到:
回到你的用例,这意味着:
categoryByItem在您所在的州引入地图,或者categoryId在您的每个items.item.id = item.id + '/' + category.id:。然后只需用“/”分割项目 ID 即可获得类别的 ID。关于检查类别 id 键是否存在的问题itemsByCategory,为什么不只在填充entities.categories对象的同时填充此对象呢?每次加载新类别(比方说, id )时,在该键下categoryId创建一个空对象(或不是空的,但具有指示卸载状态的形状)。itemsByCategorycategoryId
另一种可能性null是使用Facebook 的 idx 辅助函数,尤其是在您发现自己检查过于频繁的情况下。有了它的帮助,您的选择器将如下所示:
const isItemsLoaded = (state, categoryId) => idx(state, _ => _.itemsByCategory[categoryId].isLoaded);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
498 次 |
| 最近记录: |