在反应中使用递归函数从平面数组创建 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 树的主要内容,如果未能解决你的问题,请参考以下文章