【问题标题】:How to add or remove children under parent array using react state?如何使用反应状态在父数组下添加或删除子项?
【发布时间】:2021-02-23 10:58:28
【问题描述】:

我正在研究一个解决方案,其中我有一个包含子元素的深层父数组

这是数组的样子

[
    {
        "id": "1",
        "Name": "John Doe",
        "children":
        [
            {
                "id": "1.1",
                "name": "John doe 1.1"
            },
            {
                "id:": "1.2",
                "name:": "John doe 1.2"
            },
            {
                "id": "1.3",
                "name": "John doe 1.3",
                "children": 
                [
                    {
                        "id": "1.3.1",
                        "name": "John doe 1.3.1"
                    }
                ]
            }
        ]
    },
    {
        "id": "2",
        "Name": "Apple",
        "children":
        [
            {
                "id": "2.1",
                "name": "Apple 2.1"
            },
            {
                "id:": "1.2",
                "name:": "Apple 1.2"
            }
        ]
    }
]

基本上,我有一个功能,只要用户点击我想添加与该行相关的子级的行,我就有一个表格,

例如,每当我单击 id 为 1 的行时,我通过将行作为参数传递来调用 click 函数,找到行的索引并在其下附加子项以及维护状态,我的解决方案仅适用于嵌套的一层孩子,假设如果我想在 children 下添加 children 属性,它不起作用

这是我写的函数

const expandRow = (row) => {
      
    const index = _(this.state.data)
        .thru(function(coll) {
            return _.union(coll, _.map(coll, 'children') || []);
        })
        .flattenDeep()
        .findIndex({ id: row.id });

    console.log(index)


    if (index !== -1) {
        let prevState = [...this.state.data];
        let el = _(prevState)
            .thru(function(coll) {
                return _.union(coll, _.map(coll, 'children') || []);
          })
            .flattenDeep()
            .find({ id: row.id });
        console.log(el)
        el.children = [
            { id: '_' + Math.random().toString(36).substr(2, 5), name: "sfsdfds1", isExpanded:false,parentId:row.id },
            { id: '_' + Math.random().toString(36).substr(2, 5), name: "sfsdfds2",isExpanded:false,parentId:row.id },
        ];


        this.setState({data:[...this.state.data],prevState},()=>{console.log(this.state.data)})
      }
        updateState(row.id, { isExpanded: true });
  };

我还想与它一起维护状态,因此每当用户添加新行时,我的组件都会重新渲染。

【问题讨论】:

    标签: javascript reactjs lodash


    【解决方案1】:

    你需要递归函数。下面是我在 VueJs 中为父子深度数组编写的代码。请看一下希望它为您提供一些想法。 还有一件事我的数据结构和你的一样。

        let treeData= {
                        id:1,
                        type: 0,
                        status: 0,
                        parent_id:0,
                        children: [{
                        id:1,
                        type: 0,
                        status: 0,
                        parent_id:1,
                        children:[
                        {
                        id:1,
                        type: 0,
                        status: 0,
                        parent_id:1,
                        }
                        ]
                        }],
                    }
    
    
    
    ChangeCheckStatus(treedata, item, status) {
                        for (let i = 0; i < treedata.length; i++) {
                            if (treedata[i].id === item.id) {
                                treedata[i].selectAll = status;
                                return;
                            }
                            this.ChangeCheckStatus(treedata[i].children, item, status);
                        }
                    }
    
    makeTreeViewThroughCsvData(csvData) {
                const data = this.csvToJSON(csvData)
                this.rows_new = [...this.rows_new, ...data];
                this.rows_new.forEach((_data) => {
                    let newNode = {}
                    for (const key in _data) {
                        if (_data.hasOwnProperty(key)) {
                            newNode[key.trim()] = _data[key]
                        }
                    }
                    newNode['children'] = []
                   
                    newNode['status'] = _data.status
                    /* eslint-disable */
                    newNode = rest
                    //variable hold new tree data
                    this.treeData.push(newNode)
                })
                this.generateFinalTreeData();
            },
            generateFinalTreeData() {
                const root = []
                const nodeIds = []
                const mapping = {}
                this.treeData.forEach(node => {
                    // No parentId means Node
                    if (node.parent_id != undefined) {
                        //increment NODE ID only when parent_is is not undefined
                        nodeIds.push(node.id)
                    }
                    if (node.parent_id == 0 || node.parent_id == 1) return root.push(node);
                    // Insert node as child of parent
                    let parentKey = mapping[node.parent_id];
                    if (typeof parentKey !== "number") {
                        parentKey = this.treeData.findIndex(el => el.id === node.parent_id);
                        mapping[node.parent_id] = parentKey;
                    }
                    if (!this.treeData[parentKey].children) {
                        return this.treeData[parentKey].children = [node];
                    }
                    this.treeData[parentKey].children.push(node);
                });
                this.finalTreeData = root
                //vuex commit statement == Redux dispach
                this.$store.commit('setTreeViewData', root);
                this.$store.commit('setMaxNodeId', Math.max(...nodeIds) + 1);
            }
    

    【讨论】:

    • 但是状态不会用这个解决方案正确更新!您在更新状态时是否需要展平数组,更新状态并再次将其转换为树结构?
    • 在我的代码中,我使用 vuex 进行状态管理。在这里,我在操作之前将状态数据复制到局部变量中。一旦我得到了东西,我就会在 vuex 中更新完整的树对象
    • 我也在做同样的事情:)
    • 我正在添加另外 2 个函数,请查看它们。makeTreeViewThroughCsvData,generateFinalTreeData
    猜你喜欢
    • 2019-10-13
    • 2018-10-14
    • 1970-01-01
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 2018-09-19
    • 2022-06-10
    • 2017-03-03
    相关资源
    最近更新 更多