如何使用反应状态在父数组下添加或删除子元素?

时间:2021-02-23 10:58:28

标签: javascript reactjs lodash

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

这是数组的样子

[
    {
        "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 函数,找到行的索引并将子项附加到该行下并保持状态,我的解决方案仅适用于一级嵌套孩子,假设如果我想在孩子下添加孩子的财产,那是行不通的

这是我写的函数

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 });
  };

我还想同时保持状态,以便每当用户添加新行时,我的组件都会重新渲染。

1 个答案:

答案 0 :(得分:0)

为此您需要递归函数。下面是我在 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);
        }