英文:
Rendering Hierarchy based on data using Object.entries
问题
以下是代码的翻译部分:
export const data = {
"Category 1": [
{
key: "1",
label: "Applications",
children: [
{
key: "3",
label: "Browser",
children: [
{
key: "4",
label: "Mozilla",
children: []
},
{
key: "5",
label: "Firefox",
children: []
}
]
}
]
}
],
"Category 2": [
{
key: "2",
label: "OS",
children: [
{
key: "6",
label: "Windows",
children: []
}
]
}
]
};
import React from "react";
import TreeNode from "./TreeNode";
const Tree = ({ data = [] }) => {
return (
<div className="d-tree">
<ul className="d-flex d-tree-container flex-column">
{data.map((tree) => (
<TreeNode node={tree} />
)}
</ul>
</div>
);
};
export default Tree;
希望这有助于你在代码中理解和使用这些部分。
英文:
I am having a object that looks like the following:
export const data = {
"Category 1": [
{
key: "1",
label: "Applications",
children: [
{
key: "3",
label: "Browser",
children: [
{
key: "4",
label: "Mozilla",
children: []
},
{
key: "5",
label: "Firefox",
children: []
}
]
}
]
}
],
"Category 2": [
{
key: "2",
label: "OS",
children: [
{
key: "6",
label: "Windows",
children: []
}
]
}
]
};
This should basically draw a tree with two entries with Category 1
and Category 2
and its children should be drawn recursively.
Category 1
---- Applications
--- Browser
--- Mozilla
--- Firefox
Category 2
---- OS
--- Windows
This should be dynamically rendered. The number of first level objects will be determined using the number of keys of the object. I have tried with an array of objects and it works. But when I am having it in the above format, I am unable to render it as a tree. Help would be greatful.
Sandbox: https://codesandbox.io/s/react-hooks-counter-demo-forked-zsxsxh?file=/src/Tree.js
When I am trying it with treeData
it works, but with data
inside constants.js it doesnt work.
import React from "react";
import TreeNode from "./TreeNode";
const Tree = ({ data = [] }) => {
return (
<div className="d-tree">
<ul className="d-flex d-tree-container flex-column">
{data.map((tree) => (
<TreeNode node={tree} />
))}
</ul>
</div>
);
};
export default Tree;
I tried with Object.entries
to render the tree, it doesnt work
答案1
得分: 1
你的 data
结构与 treeData
不同,尽管子项采用相同的格式。
不是在顶层使用对象:
export const data = {
"Category 1": [ ... ],
"Category 2": [ ... ],
};
而应该使用具有 key
、label
和 children
的数组:
export const data = [
{
key: "Category 1",
label: "Category 1",
children: [ ... ]
}, ...
];
如果你真的不能编辑 data
(它就在那里...),你可以使用属性名作为 key
和 label
来映射顶层条目:
const dataAsArray = Object.entries(data).map(([key, value]) =>
({ key, label: key, children: value })
)
添加响应评论
如果这是您首选的输入格式,那么您可以将数据转换放入您的 Tree
组件中:
const Tree = ({ data = [] }) => {
const trees = React.useMemo(() => (
data instanceof Array
? data
: Object.entries(data).map(
([key, children]) => ({ key, label: key, children })
)
), [data]);
return (
<div className="d-tree">
<ul className="d-flex d-tree-container flex-column">
{trees.map((tree) => (
<TreeNode node={tree} />
))}
</ul>
</div>
);
};
英文:
Your data
structure is different from treeData
, although the children are in the same format.
Instead of an object at the top-level:
export const data = {
"Category 1": [ ... ],
"Category 2": [ ... ],
};
you should have an array with key
, label
and children
:
export const data = [
{
key: "Category 1",
label: "Category 1",
children: [ ... ]
}, ...
];
If you really can't edit the data
(it's right there ...) you could map the top-level entries using the property name as key
and label
:
const dataAsArray = Object.entries(data).map(([key, value]) =>
({ key, label: key, children: value })
)
Added in response to comment
If that's your preferred input format then you could put the data conversion into your Tree
component:
const Tree = ({ data = [] }) => {
const trees = React.useMemo(() => (
data instanceof Array
? data
: Object.entries(data).map(
([key, children]) => ({ key, label: key, children })
)
), [data]);
return (
<div className="d-tree">
<ul className="d-flex d-tree-container flex-column">
{trees.map((tree) => (
<TreeNode node={tree} />
))}
</ul>
</div>
);
};
答案2
得分: 0
In tree.js,你可以验证数据是否不是一个数组并进行转换:
const Tree = ({ data = [] }) => {
if (!(data instanceof Array)) {
data = Object.keys(data).map((key) => {
return { label: key, children: data[key] };
});
}
return (
<div className="d-tree">
<ul className="d-flex d-tree-container flex-column">
{data.map((tree) => (
<TreeNode node={tree} />
))}
</ul>
</div>
);
};
你提供的链接是一个示例的CodeSandbox链接,我不能直接转译它。
英文:
In tree.js you can validate if data is not an array and transform it:
Tree.js
const Tree = ({ data = [] }) => {
if (!(data instanceof Array)) {
data = Object.keys(data).map((key) => {
return { label: key, children: data[key] };
});
}
return (
<div className="d-tree">
<ul className="d-flex d-tree-container flex-column">
{data.map((tree) => (
<TreeNode node={tree} />
))}
</ul>
</div>
);
};
https://codesandbox.io/s/react-hooks-counter-demo-forked-3hxcgq
答案3
得分: 0
以下是您要翻译的内容:
你可以像这样编写Tree
组件,然后将Object.entries
的键(category
)和值(items
)作为props传递给TreeNode
组件。
在TreeNode
中,您可以根据是否有子节点递归渲染TreeNode
组件。这里有相关资源。
此外,您只能为第一级添加样式。
我使用了一个名为level
的prop,并将其默认设置为1,然后仅在级别为1时添加样式(出于简单起见,我使用了内联样式)。对于下一级,我通过将level prop增加1来实现。
以下是JavaScript代码的翻译部分:
const Tree = ({ data = [] }) => {
return (
<div className="d-tree">
<ul className="d-flex d-tree-container flex-column">
{Object.entries(data).map(([category, items]) => (
<TreeNode
key={category}
node={{ label: category, children: items }}
/>
))}
</ul>
</div>
);
};
const TreeNode = ({ node, level = 1 }) => {
const [childVisible, setChildVisibility] = useState(false);
const hasChild = node.children && node.children.length > 0;
const nodeStyle = level === 1 ? { fontWeight: "bold", color: "red" } : {};
return (
<li className="d-tree-node border-0">
<div className="d-flex" onClick={(e) => setChildVisibility((v) => !v)}>
<div className="col d-tree-head" style={nodeStyle}>
{node.label}
</div>
</div>
{hasChild && childVisible && (
<div className="d-tree-content">
<ul className="d-flex d-tree-container flex-column">
{node.children.map((item) => (
<TreeNode key={item.key} node={item} level={level + 1} />
)}
</ul>
</div>
)}
</li>
);
};
我已为您提供了代码的翻译部分。如果您需要任何其他帮助,请随时告诉我。
英文:
you could write the Tree
component like this and pass down the key (category
) and the value (items
) of Object.entries
as props to TreeNode
const Tree = ({ data = [] }) => {
return (
<div className="d-tree">
<ul className="d-flex d-tree-container flex-column">
{Object.entries(data).map(([category, items]) => (
<TreeNode
key={category}
node={{ label: category, children: items }}
/>
))}
</ul>
</div>
);
};
In the TreeNode
you can recursively render TreeNode
components based on if it has children or not. Here is a resource on that.
Also you can add styles only to the first level.
I used a prop called level
and defaulted it to 1, then I give styles only if the level is 1 (used inline styles for simplicity). For the next levels, I increment the level prop by 1.
const TreeNode = ({ node, level = 1 }) => {
const [childVisible, setChildVisiblity] = useState(false);
const hasChild = node.children && node.children.length > 0;
const nodeStyle = level === 1 ? { fontWeight: "bold", color: "red" } : {};
return (
<li className="d-tree-node border-0">
<div className="d-flex" onClick={(e) => setChildVisiblity((v) => !v)}>
<div className="col d-tree-head" style={nodeStyle}>
{node.label}
</div>
</div>
{hasChild && childVisible && (
<div className="d-tree-content">
<ul className="d-flex d-tree-container flex-column">
{node.children.map((item) => (
<TreeNode key={item.key} node={item} level={level + 1} />
))}
</ul>
</div>
)}
</li>
);
};
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
const data = { "Category 1": [ { key: "1", label: "Applications", children: [ { key: "3", label: "Browser", children: [ { key: "4", label: "Mozilla", children: [] }, { key: "5", label: "Firefox", children: [] } ] } ] } ], "Category 2": [ { key: "2", label: "OS", children: [ { key: "6", label: "Windows", children: [] } ] } ]};
const TreeNode = ({ node, level = 1 }) => {
const [childVisible, setChildVisiblity] = React.useState(false);
const hasChild = node.children && node.children.length > 0;
const nodeStyle = level === 1 ? { fontWeight: "bold", color: "red" } : {};
return (
<li className="d-tree-node border-0">
<div className="d-flex" onClick={(e) => setChildVisiblity((v) => !v)}>
{hasChild && (
<div
className={`d-inline d-tree-toggler ${
childVisible ? "active" : ""
}`}
>
{'>'}
</div>
)}
<div className="col d-tree-head" style={nodeStyle}>
{node.label}
</div>
</div>
{hasChild && childVisible && (
<div className="d-tree-content">
<ul className="d-flex d-tree-container flex-column">
{node.children.map((item) => (
<TreeNode key={item.key} node={item} level={level + 1} />
))}
</ul>
</div>
)}
</li>
);
};
const Tree = ({ data = [] }) => {
return (
<div className="d-tree">
<ul className="d-flex d-tree-container flex-column">
{Object.entries(data).map(([category, items]) => (
<TreeNode
key={category}
node={{ label: category, children: items }}
/>
))}
</ul>
</div>
);
};
const TreeList = () => {
return <Tree data={data} />;
};
ReactDOM.render(<TreeList />, document.querySelector('.app'));
<!-- language: lang-css -->
.d-tree-container {
list-style: none;
padding: 0;
}
.d-tree-node {
padding: 0.75rem 1.25rem;
}
.d-tree-toggler.active {
transform: rotate(45deg);
}
<!-- language: lang-html -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='app'></div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论