Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/422.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何从对象中递归删除子对象?_Javascript_Arrays_Reactjs_React Native - Fatal编程技术网

Javascript 如何从对象中递归删除子对象?

Javascript 如何从对象中递归删除子对象?,javascript,arrays,reactjs,react-native,Javascript,Arrays,Reactjs,React Native,我正在研究解决方案 我已经创建了基本的树型表,每当用户单击expand data时,与单击的行相关的数据就会根据行数据显示在它下面 我已经实现了扩展/折叠到N个嵌套级别的基本功能 但我只遇到一个问题,所以基本上所有行都有基于数组的条件展开按钮,数组有多个值 假设它是一个拆分数组,有3个条目:县、市、州 默认加载的数据将从api中获取,现在我必须检查数组中是否有可用的拆分!如果是,则显示展开按钮 考虑一下这个场景 const split = ["country","c

我正在研究解决方案

我已经创建了基本的树型表,每当用户单击expand data时,与单击的行相关的数据就会根据行数据显示在它下面

我已经实现了扩展/折叠到N个嵌套级别的基本功能

但我只遇到一个问题,所以基本上所有行都有基于数组的条件展开按钮,数组有多个值

假设它是一个拆分数组,有3个条目:县、市、州

默认加载的数据将从api中获取,现在我必须检查数组中是否有可用的拆分!如果是,则显示展开按钮

考虑一下这个场景

const split = ["country","city","state"]
这是Ui的外观

+ Data_1
+ Data_2
点击按钮+新的数据表行将根据下一次分割呈现,在我们的情况下,它是国家,因此视觉表现将如下

- Data_1
   Country_1
   Country_2
+ Data_2
    - Data_1
       - Country_1
           City_1
           City_2
       + Country_2
    + Data_2
这里国家并没有展开按钮,因为用户还并没有添加下一个分割,让我们添加城市,并假设用户点击了国家1,所以数据如下

- Data_1
   Country_1
   Country_2
+ Data_2
    - Data_1
       - Country_1
           City_1
           City_2
       + Country_2
    + Data_2
我的解决方案运行良好,直到这个级别,现在让我们假设用户已经从拆分中删除了国家/地区,国家/地区和城市的所有节点都应该删除,并且数据_1的-图标应该更改为+

这是我的密码

import React, {useState, useEffect, useRef, Fragment} from "react";
  import _ from "lodash";
  import axios from "axios";

  class TableRowData extends React.Component {
    state = {
      showIcon: false,
      selection: [],
      data: [],
      splitOption: ["campid"]
    };
    constructor(props) {
      super(props);
    }

    componentDidMount() {
      const checkIfSplitExistOnMount = (currentSplit) => {
        const i = _.findIndex(this.state.splitOption, function(el) {
          return el === currentSplit;
        });

        if (this.state.splitOption[i + 1]) {
          return this.state.splitOption[i + 1];
        } else {
            return null;
        }
      }
      const getReportData = () => {
        axios.get("https://jsonplaceholder.typicode.com/users?_start=0&_limit=1").then((res) => {
          const rowData = res.data.map((row) => {
            row.name = this.state.splitOption[0];
            row.isExpanded = false;
            row.currentSplit = this.state.splitOption[0];
            row.nextSplit = checkIfSplitExistOnMount(this.state.splitOption[0])
            row.parentId = 0;
            row.isVisble = true;
            //console.log(row)
            return row;
          });
          this.setState({
            data: rowData
          }, () => { //console.log(this.state.data)
          });
        });
      }
      getReportData()
    }

    render() {
      // update state function
      const updateState = () => {
        this.setState({
          data: [...this.state.data],
          splitOption: [...this.state.splitOption],
          selection: [...this.state.selection],
        }, () => {})
      }

      // recusively update parent and child
      const recursion = (obj) => {
         let row = obj;
         row.isExpanded = row.isExpanded;
         row.currentSplit = row.currentSplit;
         row.nextSplit = checkIfSplitExist(row.currentSplit)

         if (row.children && row.children.length > 0) { // check if has children
            row.children.forEach(v => { // if has children do the same recursion for every children
              recursion(v);
            });
         }
         return row; // return final new object
       }

       const recursionDel = (obj,split) => {
           var row = obj;
           row.currentSplit = row.currentSplit;
           row.nextSplit = checkIfSplitExist(row.currentSplit)
           if (row.children && row.children.length > 0) { // check if has children
             row.children.forEach(v => { // if has children do the same recursion for every children
               recursionDel(v);
             });
          }
          return row; // return final new object
        }

      // function to check if next split is there or not if there than return nextsplit
      const checkIfSplitExist = (currentSplit) => {
        const i = _.findIndex(this.state.splitOption, function(el) {
          return el === currentSplit;
        });
        if(i !== -1) {
          if (this.state.splitOption[i + 1]) {
            return this.state.splitOption[i + 1];
           } else {
            return null;
          }
        }

      }

      // recursive update whenever split added
      const recursiveUpdate = (data) => {
        const prevData = [...data];
        return prevData.map((row) => {
          const updatedData =  recursion(row);
          return row;
        });
      }

      // function to delete child and parent node recursively
      const recursiveDelete = (data,split) => {
        const prevData = [...data];
        return prevData.map((row) => {
          const data =  recursionDel(row,split);
          return row;
        });
      }

      const addNewSplit = (split) => {
        const i = _.findIndex(this.state.splitOption, function(el) {
          return el === split;
        });
        if(i === -1) {
            this.setState(
              {
                splitOption:[...this.state.splitOption,split]
              },
              ()=>{
                var rowData = recursiveUpdate(this.state.data)
                this.setState({data:rowData})
              }
          );
        } else {
          const prevData = [...this.state.splitOption];
          var index = prevData.indexOf(split);
          prevData.splice(index,1)
          if(index!==-1) {
            this.setState(
                {
                    splitOption:prevData
                },
                ()=> {
                  var rowData = recursiveDelete(this.state.data,split)
                  this.setState({data:rowData})
                }
              )
          }
        }

      }

      // add lazyload expand data
      const ExpandableTableRow = ({rows}) => {

        const expandRow = (row) => {
          row.children = [
            {
              id: "_" + Math.random().toString(36).substr(2, 5),
              name: row.id + "_" + row.nextSplit,
              isExpanded: false,
              parentId: row.id,
              currentSplit: row.nextSplit,
              nextSplit: checkIfSplitExist(row.nextSplit),
              isVisble:true
            }, {
              id: "_" + Math.random().toString(36).substr(2, 5),
              name: row.id + "_" + row.nextSplit,
              isExpanded: false,
              parentId: row.id,
              currentSplit: row.nextSplit,
              nextSplit: checkIfSplitExist(row.nextSplit),
              isVisble:true
            }
          ];
          row.isExpanded = true;
          updateState();
        };

        // call whenever - click
        const collapseRow = (row) => {
          delete row.children;
          row.isExpanded = false;
          updateState();
        };

        // toggle
        const ExpandCollapsToggle = ({row, expandRow, collapseRow}) => {
          // display +/- only if nextsplit is not undefined or null
          if (row.nextSplit) {
            if (row.isExpanded === true) {
              return (<button type="button" onClick={() => collapseRow(row)}>
                -
              </button>);
            } else {
              return (<button type="button" onClick={() => expandRow(row)}>
                +
              </button>);
            }
          } else {
            return null;
          }
        };



        if (rows) {
          return rows.map((row) => {
          //  if(!_.isEmpty(row)) {
              return (<Fragment key={row.id}>
                <tr key={row.id}>
                  <td>
                    <ExpandCollapsToggle row={row} expandRow={expandRow} collapseRow={collapseRow}/>{" "}
                    {row.split}
                    - {row.id}
                  </td>
                  <td>{row.name}</td>
                </tr>
                <ExpandableTableRow rows={row.children}/>
              </Fragment>);
          //  }

          });
        } else {
          return null;
        }
      };

      const splitData = this.state.splitOption.map((ob) => {
        return (<Fragment key={ob}><span>{ob}</span> > </Fragment>)
      })

      if (this.state.data) {
        return (
          <Fragment>
            {splitData} <br/>
            <button onClick = {()=>addNewSplit("name")}>camp name</button>
            <button onClick = {()=>addNewSplit("os")}>os</button>
            <button onClick = {()=>addNewSplit("country")}>country</button>
          <ExpandableTableRow rows={this.state.data} />
        </Fragment>
        );
      } else {
        return null;
      }
    }
  }

  export default TableRowData;
import React,{useState,useffect,useRef,Fragment}来自“React”;
从“洛达斯”进口;
从“axios”导入axios;
类TableRowData扩展了React.Component{
状态={
showIcon:false,
选择:[],
数据:[],
拆分选项:[“campid”]
};
建造师(道具){
超级(道具);
}
componentDidMount(){
常量checkIfSplitExistOnMount=(currentSplit)=>{
const i=u.findIndex(this.state.splitOption,函数(el){
返回el==currentSplit;
});
if(this.state.splitOption[i+1]){
返回此.state.splitOption[i+1];
}否则{
返回null;
}
}
const getReportData=()=>{
axios.get(“https://jsonplaceholder.typicode.com/users?_start=0&_limit=1)然后((res)=>{
const rowData=res.data.map((行)=>{
row.name=this.state.splitOption[0];
row.isExpanded=false;
row.currentSplit=此.state.splitOption[0];
row.nextSplit=checkIfSplitExistOnMount(this.state.splitOption[0])
row.parentId=0;
row.isVisble=true;
//console.log(行)
返回行;
});
这是我的国家({
数据:行数据
},()=>{//console.log(this.state.data)
});
});
}
getReportData()
}
render(){
//更新状态函数
const updateState=()=>{
这是我的国家({
数据:[…this.state.data],
splitOption:[…this.state.splitOption],
选择:[…this.state.selection],
}, () => {})
}
//重复更新父级和子级
常量递归=(obj)=>{
设row=obj;
row.isExpanded=row.isExpanded;
row.currentSplit=row.currentSplit;
row.nextSplit=checkIfSplitExist(row.currentSplit)
如果(row.children&&row.children.length>0){//检查是否有子级
forEach(v=>{//if)让子对象对每个子对象执行相同的递归
递归(v);
});
}
返回行;//返回最终的新对象
}
常量递归del=(对象,拆分)=>{
var行=obj;
row.currentSplit=row.currentSplit;
row.nextSplit=checkIfSplitExist(row.currentSplit)
如果(row.children&&row.children.length>0){//检查是否有子级
forEach(v=>{//if)让子对象对每个子对象执行相同的递归
递归del(v);
});
}
返回行;//返回最终的新对象
}
//函数检查是否存在下一次拆分,如果存在下一次拆分,则返回下一次拆分
const checkIfSplitExist=(currentSplit)=>{
const i=u.findIndex(this.state.splitOption,函数(el){
返回el==currentSplit;
});
如果(i!==-1){
if(this.state.splitOption[i+1]){
返回此.state.splitOption[i+1];
}否则{
返回null;
}
}
}
//添加拆分时的递归更新
常量递归更新=(数据)=>{
常量prevData=[…数据];
返回prevData.map((行)=>{
const updatedata=递归(行);
返回行;
});
}
//函数递归删除子节点和父节点
常量递归删除=(数据,拆分)=>{
常量prevData=[…数据];
返回prevData.map((行)=>{
const data=recursionDel(行、拆分);
返回行;
});
}
const addNewSplit=(拆分)=>{
const i=u.findIndex(this.state.splitOption,函数(el){
返回el==拆分;
});
如果(i==-1){
这是我的国家(
{
splitOption:[…this.state.splitOption,split]
},
()=>{
var rowData=recursiveUpdate(this.state.data)
this.setState({data:rowData})
}
);
}否则{
const prevData=[…this.state.splitOption];
var指数=prevData.indexOf(分割);
prevData.拼接(索引,1)
如果(索引!=-1){
这是我的国家(
{
拆分选项:prevData
},
()=> {
var rowData=recursiveDelete(this.state.data,split)
this.setState({data:rowData})
}
)
}
}
}
//添加lazyload扩展数据
const ExpandableTableRow=({rows})=>{
欺骗