[英]Need help creating a folder tree component in React with the given json structure
我正在尝试构建一个文件夹树组件,最初该组件只会呈现第一层的项目名称(item1、item2、item3),然后当单击特定项目时,它会显示下一层列出的所有内容对于该项目(即单击item1将显示item1.1和item1.2,单击item1.1将显示item1.1.1 )。 这应该在一个循环中完成,直到它到达只有属性(attr1、attr2、attr3)的最后一层。
注意:出于演示目的,我已经简化了项目名称,但实际上它们并不遵循特定的模式/命名系统。
import React, {useState, useEffect} from 'react';
const Testing = () => {
const [expand, setExpand] = useState(false);
const data = {
"item1": {
"item1.1": {
"item1.1.1": {
"item1.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
},
"item1.2": {
"item1.2.1": {
"item1.2.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
},
"item2": {
"item2.1": {
"item2.1.1": {
"item2.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
},
"item2.1.2": {
"item2.1.2.1": {
"attr1": [],
"attr2": "",
"attr3": []
},
"item2.1.2.2": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
},
"item3": {
"item3.1": {
"item3.1.1": {
"item3.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
},
"item3.1.2": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
}
function parse(data) {
if (typeof data === 'object') {
return (
<li>
<ul>
{Object.entries(data).map(([key, value]) => (
<>
<li>
{key}: {typeof value === 'string' ? value : ''}
</li>
{parse(value)}
</>
))}
</ul>
</li>
);
}
if (typeof data === 'object') return (<li>{data}</li>);
return null;
}
return (
<div>
<div className="App">
{Object.entries(data).map(([key, value]) => {
return (
<ul>
<span onClick={() => setExpand(!expand)}>{key}</span>
<br />
<div style={{ display: expand ? "block" : "none", paddingLeft: 15 }}>
{parse(value)}
</div>
</ul>
);
})}
</div>
</div>
)
}
export default Testing;
这是我现在用上面的代码得到的输出图片: current output ; 它在列表中显示 item1、item2、item3; 但是当我点击它们中的任何一个时,它只会呈现其他所有内容,我正在尝试找到一种方法,使其行为类似于文件目录树,如下面的演示所示: https ://codesandbox.io/s /文件夹结构-t6oj4
问题在于,在演示中,他们使用了一个递归组件,该组件具有自己的expand
状态,并通过钩子进行管理。 因此,每个Folder
都将具有其范围内的expand
变量的不同值。
另一方面,您的Testing
组件管理单个expand
状态,并且整个渲染为每个“文件夹”使用该状态,这就是为什么当您单击文件夹时它会切换整个组件的状态,您应该做的是重构您的组件,以便它还在每个文件夹中管理自己的状态,就像在演示中一样:
import React, { useState } from "react";
function Folder ({ name, file }) {
const [expand, setExpand] = useState(false);
if (typeof file !== "object") return <span>{file}</span>;
return (
<div>
<span onClick={() => setExpand(!expand)}>{name}</span>
<br/>
<div style={{ display: expand ? "block" : "none", paddingLeft: 15 }} >
{
Object.entries(file).map(([key, value]) => (
<Folder key={key} name={key} file={value} />
))
}
</div>
</div>
);
}
然后在你的组件中调用它:
import React from 'react';
const Testing = () => {
const data = {
"item1": {
"item1.1": {
"item1.1.1": {
"item1.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
},
"item1.2": {
"item1.2.1": {
"item1.2.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
},
"item2": {
"item2.1": {
"item2.1.1": {
"item2.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
},
"item2.1.2": {
"item2.1.2.1": {
"attr1": [],
"attr2": "",
"attr3": []
},
"item2.1.2.2": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
},
"item3": {
"item3.1": {
"item3.1.1": {
"item3.1.1.1": {
"attr1": [],
"attr2": "",
"attr3": []
}
},
"item3.1.2": {
"attr1": [],
"attr2": "",
"attr3": []
}
}
}
}
return (
<div>
<div className="App">
<Folder name="/root" file={data} />
</div>
</div>
)
}
编辑:重构代码,以便只有选定的文件夹在单击时展开
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.