我正在尝试使用具有Redux状态的多层嵌套数组,并且遇到了复杂性(或理解性)问题。我刚刚开始学习react(与redux一起使用),并认为我把它做的太复杂了,无法正确地对状态建模。
(与Azure一起使用)我的状态如下所示:
有很多租户。每个租户可以具有1个或多个订阅。每个订阅可以具有1个或多个资源组。每个资源组可以具有1个或更多资源。每个资源可以具有1个或多个标签。
看起来像这样:
tenants: [
{
DisplayName: "blah",
DomainName: "blah.onmicrosoft.com",
TenantId: "72f988bf-1111-1111-1111-111111111111",
active: false,
subs: []
},
{
DisplayName: "blah2",
DomainName: "blah2.onmicrosoft.com",
TenantId: "57aa6e76-1111-1111-1111-111111111111",
active: true,
subs: [
{
subId: '444-555',
subName: 'SubName',
state: "enabled",
active: true,
resourceGroups: [
{
name:"one",
id: "/blah/123/456",
resources: [
{
name: "vm1",
type: "Microsoft.Compute/VirtualMachine"
},
{
name: "vm2",
type: "Microsoft.Compute/VirtualMachine"
}
]
},
{
name:"two",
id: "/blah/555/222",
resources: [
{
name: "vm3",
type: "Microsoft.Compute/VirtualMachine"
},
{
name: "vm4",
type: "Microsoft.Compute/VirtualMachine"
}
]
},
]
}
]
}
]
}
我正在努力了解如何跟踪和修改每个项目的状态,例如在UI上显示/不显示,单击按钮等。因此,例如,如果我想要一个嵌套菜单,跟踪什么是不能根据单击的内容正确显示和反映,以折叠或展开给定菜单。因此,例如,如果我单击“承租人”按钮/框/标题,它将折叠所有子项。
我是否按状态“深度级别”创建函数并传递索引?所以例如如果我想使用虚拟机和标签,可以通过租户索引,子索引,RG索引等吗?我认为可以,但是听起来太糟糕了。
还是我以某种方式将状态拆分为多个化简器,也许一个用于租户,一个用于租户等?并做一些关键参考作为状态属性,例如在resourceGroup reducer中,是否有一个“ sub”键指向订阅索引?
任何有关如何解决此问题的建议或想法都是很好的。谢谢。
编辑:我以为我会更新最终要做的事情。
状态现在看起来像这样:
resources: [
{
type: "tenant",
displayName: "Microsoft",
shortId: "72f988bf-1111-1111-1111-111111111111",
longId: "/blah/123/456/789",
isVisible: false,
info: {
active: false,
domainName: "microsoft.onmicrosoft.com",
},
children: []
},
{
type: "tenant",
displayName: "blahdy blah blah",
shortId: "57aa6e76-1111-1111-1111-111111111111",
longId: "/blah/123/456",
isVisible: false,
info: {
active: true,
domainName: "blah.onmicrosoft.com",
},
children: [2, 7]
},
{
type: "subscription",
shortId: '444-55522',
longId: "/blah/123/456/789",
displayName: 'SubName',
isVisible: false,
info: {
active: true,
state: "enabled",
},
children: [3,4]
}
]
每个属性的“子级”数组是对作为“嵌套”子级的索引的引用。
现在,从这里,我可以递归地渲染组件,有条件地检查子对象,如果有的话,则映射到递归渲染中。
注意:要递归地呈现从redux获得其状态映射的组件,您必须先定义一个const,导出该const,然后在递归调用中使用该const:
var ResourceWrapper = connect(mapStateToProps, mapDispatchToProps)(Resource);
export default ResourceWrapper;
答案 0 :(得分:1)
还是我以某种方式将状态拆分为多个化简器,也许一个用于租户,一个用于租户等?
确保您需要将状态分成多个化简器(即Single Responsibility Principle)
将商店视为文档树。您可以将整个树分成较小的树,从而使子问题以某种方式隔离。
因此,基本上,您具有tenants/subs/resourceGroups/resources
树结构和目录结构。
您的操作格式还应该与目录结构匹配(即tenants/subs/add
用于添加对特定租户的订阅,或tenants/remove
用于移除租户)。拥有这种格式将有助于使用redux-dev-tools
进行操作过滤。
因此,每个文件夹都有它们自己的简化程序,例如tenants
,在这里它仅处理商店的“承租人切片”。对于Tenant Reducer,它可以处理会影响Tenant-Slice的与Tenant相关的UI操作。
P.S,具有类似于API响应的状态结构是一个优势(从某种意义上讲,不再需要转换)。
答案 1 :(得分:0)
也许这会有所帮助:
在构建React和Redux应用程序时,通常在component文件夹中为每个组件创建一个文件夹。每个文件夹将具有Component.js文件以及component.action.js和component.reducer.js。然后,使用react-redux包中的combineReducers组合reducer-我的惯例是将其放置在与商店相同的文件夹中,然后将其导入并传递到商店中,然后再从react-redux传递到Provider中,其中包装了App组件:component。
应用的初始状态声明为const initialState = {var1:value1,var2:value2}。将此作为第一个参数传递到reducer中,以将初始状态和action设置为第二个参数:cost reducer =(state = initialState,action)=> {…}。
reduceers通常是一个打开action.type的switch语句。该动作将具有您在动作创建者上指定的其他变量。减速器通常以action.someVariable返回新状态。我最喜欢这样做的约定是:return {…state,someVariable:“ newValue”,anotherVariable:“ anotherValue”}。
您可以管理组件是否在组件上显示isVisible变量。如果您在同一组件中有一个下拉菜单。它会有一个动作和一个动作创建者。操作导出const TOGGLE_MENU ='TOGGLE_MENU'并导出const toggleMenu =()=>({type:TOGGLE_MENU});缩小器在打开TOGGLE_MENU(已导入到缩小器)时将返回{…状态,isVisible:!state.isVisible}。您将在化简版上方声明的initialState中指定isVisible:false。