在反应中使用递归函数从平面数组创建 JSX 树

Posted

技术标签:

【中文标题】在反应中使用递归函数从平面数组创建 JSX 树【英文标题】:Create JSX tree from flat Array with recursive function in react 【发布时间】:2020-09-16 19:25:32 【问题描述】:

我真的需要你的帮助来使用递归函数从平面数组中创建 JSX 树。

目前只有1到6项正确显示,之后递归停止

1) 我的平面 JSON 数据是:(但它可能有 1000 多个项目)

const itemsData = [

  "Level": 1,
  "Type of activity": "Consolidated task",
  "ID": 118027222233,
  "Name": "Name 1"
,

  "Level": 2,
  "Type of activity": "Consolidated task",
  "ID": 118636886633,
  "Name": "Name 2"
,

  "Level": 3,
  "Type of activity": "Consolidated task",
  "ID": 118637048333,
  "Name": "Name 3"
,

  "Level": 4,
  "Type of activity": "task",
  "ID": 118637035433,
  "Name": "Name 4"
,

  "Level": 4,
  "Type of activity": "task",
  "ID": 118841127933,
  "Name": "Name 5"
,

  "Level": 4,
  "Type of activity": "task",
  "ID": 118841156833,
  "Name": "Name 6"
,

  "Level": 3,
  "Type of activity": "Consolidated task",
  "ID": 118637046733,
  "Name": "Name 9"
,

  "Level": 4,
  "Type of activity": "Consolidated task",
  "ID": 118744514633,
  "Name": "Name 10"
,

  "Level": 5,
  "Type of activity": "task",
  "ID": 118637033033,
  "Name": "Name 11"
,

  "Level": 5,
  "Type of activity": "task",
  "ID": 118637031033,
  "Name": "Name 13"
,

  "Level": 2,
  "Type of activity": "Consolidated task",
  "ID": 118636886633,
  "Name": "Name 19"
,

  "Level": 3,
  "Type of activity": "task",
  "ID": 118637048333,
  "Name": "Name 20"
,

  "Level": 3,
  "Type of activity": "task",
  "ID": 118637048333,
  "Name": "Name 21"
]

2) 我当前的递归函数如下所示: 但只有项目 1 到 6 正确显示。

const RecursiveFunction = (currentItem, currentLevel) => 

//LOOP  AS LONG AS CURRENTITEM < ITEMS DATA LENGTH 
while(currentItem < itemsData.length)

    //IF CONSOLODATED TASK CREATE CONTAINER
    if(itemsData[currentItem]["Type of activity"] === "Consolidated task")


        //TEST IF CHILD RELATED TO LEVEL
        if(currentLevel < itemsData[currentItem].Level )


            //LINE COUNTER
            currentItem++;

            //RETURN
            return (
                <div className="conso-container">
                    <div className="conso-title">
                        itemsData[currentItem - 1].Name
                    </div>
                    <RecursiveFunction currentItem=currentItem currentLevel=itemsData[currentItem-1].Level />
                </div>
            )
        

    else

        //CURRENT TASK LIST ON A BLOCK
        let taskList = [];

        //WHILE IS A TASK
        while(currentItem < itemsData.length && itemsData[currentItem]["Type of activity"] !== "Consolidated task")

            //LIST ALL THE TASK
            taskList.push(<div className="task-title">itemsData[currentItem].Name</div>)
            currentItem++;

        

        // RETURN    
        return (
            <div className="task-container">
                taskList
            </div>
        )
    

3)我的渲染是

class RoadMapItems extends React.Component 


render()
    return( 
        <div className="tree">
            <RecursiveFunction currentItem=0 currentLevel=0 />
        </div>
    )
export default RoadMapItems;

【问题讨论】:

真正的问题是什么? :) 实际上没有任何效果...我链接了两张图片以向您展示我的目标是什么。但我不知道我的策略是否正确 @julienlaurent 问题是你将items 作为一个完整的数组再次传递,这意味着它第一次传递了 10 个项目,而第一次递归你又传递了 10 个项目,所以它会无限循环 既然有flatList,为什么还要有递归函数 数组总是有序的吗?如果您在孩子上有一个 parentID 字段可能会有所帮助,但如果他们总是正确排序,我想这可以即时完成。 @ShubhamKhatri 是正确的,使用平面表示,您不需要递归,如果您将平面转换为嵌套(parentID 会有所帮助)或者如果您的初始数据是嵌套的,那么您将需要递归。 【参考方案1】:

这应该可以。比我最初想象的要难一点,哈哈。 ?

您确实需要转换为嵌套数据结构,然后递归地映射它以提供所需的输出:

以下和此处的完整演示:https://codepen.io/Alexander9111/pen/pojXBWX

function MyTable(props) 
  const initState = [
    
      Level: 1,
      "Type of activity": "Consolidated task",
      ID: 118027222233,
      Name: "Name 1"
    ,
    
      Level: 2,
      "Type of activity": "Consolidated task",
      ID: 118636886633,
      Name: "Name 2"
    ,
    
      Level: 3,
      "Type of activity": "Consolidated task",
      ID: 118637048333,
      Name: "Name 3"
    ,
    
      Level: 4,
      "Type of activity": "task",
      ID: 118637035433,
      Name: "Name 4"
    ,
    
      Level: 4,
      "Type of activity": "task",
      ID: 118841127933,
      Name: "Name 5"
    ,
    
      Level: 4,
      "Type of activity": "task",
      ID: 118841156833,
      Name: "Name 6"
    ,
    
      Level: 3,
      "Type of activity": "Consolidated task",
      ID: 118637046733,
      Name: "Name 9"
    ,
    
      Level: 4,
      "Type of activity": "Consolidated task",
      ID: 118744514633,
      Name: "Name 10"
    ,
    
      Level: 5,
      "Type of activity": "task",
      ID: 118637033033,
      Name: "Name 11"
    ,
    
      Level: 5,
      "Type of activity": "task",
      ID: 118637031033,
      Name: "Name 13"
    ,
    
      Level: 2,
      "Type of activity": "Consolidated task",
      ID: 118636886633,
      Name: "Name 19"
    ,
    
      Level: 3,
      "Type of activity": "task",
      ID: 118637048333,
      Name: "Name 20"
    ,
    
      Level: 3,
      "Type of activity": "task",
      ID: 118637048333,
      Name: "Name 21"
    ,
    
      Level: 2,
      "Type of activity": "Consolidated task",
      ID: 128637048333,
      Name: "Name 22"
    ,
    
      Level: 3,
      "Type of activity": "task",
      ID: 138637048333,
      Name: "Name 23"
    ,
    
      Level: 1,
      "Type of activity": "Consolidated task",
      ID: 148637048333,
      Name: "Name 24"
    ,
    
      Level: 2,
      "Type of activity": "task",
      ID: 158637048333,
      Name: "Name 25"
    
  ];
  const [state, setState] = React.useState(initState);

  const table = (
    <table>
      <tr key="header">
        Object.keys(state[0]).map((key) => (
          <th>key</th>
        ))
      </tr>
      state.map((item) => (
        <tr key=item.id>
          Object.values(item).map((val) => (
            <td>val</td>
          ))
        </tr>
      ))
    </table>
  );

  let currPointer = null;
  const listOfPointers = [];
  const nestedArrs = state.reduce((aggArr, item) => 
    //console.log(listOfPointers)
    if (item.Level == 1) 
      aggArr.push(item);
    
    else if (item.Level > currPointer.Level) 
      currPointer.children.push(item);
    
    else if (item.Level <= currPointer.Level) 
      while (item.Level <= currPointer.Level) 
        listOfPointers.pop();
        currPointer = listOfPointers[listOfPointers.length - 1];
      
      currPointer.children.push(item);
    
    
    item.children = [];
    currPointer = item;
    listOfPointers.push(currPointer);

    return aggArr;
  , []);

  //console.log(nestedArrs);

  const nestedDivs = (
    <div>
      (function mapChildren(data) 
        return data.map((d, i) => 
          if (d["Type of activity"] != "task") 
            return (
              <div className="level_" + d.Level>
                <span>d.Level + " : " + d.Name</span>
                mapChildren(d.children)
              </div>
            );
           else 
            return (
              <div className="level_" + d.Level + " task">
                <span>d.Level + " : " + d.Name</span>
              </div>
            );
          
        );
      )(nestedArrs)
    </div>
  );
  //console.log(nestedDivs);

  return (
    <div>
      table
      nestedDivs
    </div>
  );


ReactDOM.render(<MyTable />, document.getElementById("target"));
th,
td 
  border: 1px solid black;
  margin: 0px 0px;
  padding: 5px 5px;

div 
  padding: 10px;
  margin: 10px;

.level_1 
  background-color: blue;

.level_2 
  background-color: orange;

.level_3 
  background-color: green;

.level_4 
  background-color: yellow;

.task 
  background-color: white !important;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="target"></div>

输入:

输出:

【讨论】:

非常感谢@AlexL!完美传递给嵌套数据。递归函数非常好,正是我要找的!这是我的第一个 javascript 函数之一,目前它对我来说有点复杂,但你的例子看起来很清楚!再次感谢 很高兴听到我的答案很明确?而且很有帮助?递归会很快变得复杂和混乱,但稍微练习一下,它会非常强大!祝你好运!

以上是关于在反应中使用递归函数从平面数组创建 JSX 树的主要内容,如果未能解决你的问题,请参考以下文章

从分层数组Ruby生成平面数组的递归函数[关闭]

反应递归地创建动态树

使用带有递归的reduce函数从多级树中生成一个扁平的id数组?

从数据库结果生成多维数组的递归函数

从嵌套对象数组中递归创建字符串?

使用递归创建树