React-redux嵌套状态,使用嵌套数组

时间:2019-05-21 01:57:16

标签: redux nested react-redux state

我正在尝试使用具有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;

2 个答案:

答案 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。