使用Object.entries根据数据渲染层次结构。

huangapple go评论69阅读模式
英文:

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 = {
  &quot;Category 1&quot;: [
    {
      key: &quot;1&quot;,
      label: &quot;Applications&quot;,
      children: [
        {
          key: &quot;3&quot;,
          label: &quot;Browser&quot;,
          children: [
            {
              key: &quot;4&quot;,
              label: &quot;Mozilla&quot;,
              children: []
            },
            {
              key: &quot;5&quot;,
              label: &quot;Firefox&quot;,
              children: []
            }
          ]
        }
      ]
    }
  ],
  &quot;Category 2&quot;: [
    {
      key: &quot;2&quot;,
      label: &quot;OS&quot;,
      children: [
        {
          key: &quot;6&quot;,
          label: &quot;Windows&quot;,
          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 &quot;react&quot;;
import TreeNode from &quot;./TreeNode&quot;;

const Tree = ({ data = [] }) =&gt; {
  return (
    &lt;div className=&quot;d-tree&quot;&gt;
      &lt;ul className=&quot;d-flex d-tree-container flex-column&quot;&gt;
        {data.map((tree) =&gt; (
          &lt;TreeNode node={tree} /&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
};

export default Tree;

I tried with Object.entries to render the tree, it doesnt work

答案1

得分: 1

你的 data 结构与 treeData 不同,尽管子项采用相同的格式。

不是在顶层使用对象:

export const data = {
  &quot;Category 1&quot;: [ ... ],
  &quot;Category 2&quot;: [ ... ],
};

而应该使用具有 keylabelchildren 的数组:

export const data = [
  {
    key: &quot;Category 1&quot;,
    label: &quot;Category 1&quot;,
    children: [ ... ]
  }, ...
];

如果你真的不能编辑 data(它就在那里...),你可以使用属性名作为 keylabel 来映射顶层条目:

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 (
    &lt;div className=&quot;d-tree&quot;&gt;
      &lt;ul className=&quot;d-flex d-tree-container flex-column&quot;&gt;
        {trees.map((tree) => (
          &lt;TreeNode node={tree} /&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
};
英文:

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 = {
  &quot;Category 1&quot;: [ ... ],
  &quot;Category 2&quot;: [ ... ],
};

you should have an array with key, label and children:

export const data = [
  {
    key: &quot;Category 1&quot;,
    label: &quot;Category 1&quot;,
    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]) =&gt;
  ({ 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 = [] }) =&gt; {
  const trees = React.useMemo(() =&gt; (
    data instanceof Array
      ? data
      : Object.entries(data).map(
          ([key, children]) =&gt; ({ key, label: key, children })
      )
  ), [data]);
    
  return (
    &lt;div className=&quot;d-tree&quot;&gt;
      &lt;ul className=&quot;d-flex d-tree-container flex-column&quot;&gt;
        {trees.map((tree) =&gt; (
          &lt;TreeNode node={tree} /&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
};

答案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 = [] }) =&gt; {
  if (!(data instanceof Array)) {
    data = Object.keys(data).map((key) =&gt; {
      return { label: key, children: data[key] };
    });
  }

  return (
    &lt;div className=&quot;d-tree&quot;&gt;
      &lt;ul className=&quot;d-flex d-tree-container flex-column&quot;&gt;
        {data.map((tree) =&gt; (
          &lt;TreeNode node={tree} /&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
};

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 = [] }) =&gt; {
  return (
    &lt;div className=&quot;d-tree&quot;&gt;
      &lt;ul className=&quot;d-flex d-tree-container flex-column&quot;&gt;
        {Object.entries(data).map(([category, items]) =&gt; (
          &lt;TreeNode
            key={category}
            node={{ label: category, children: items }}
          /&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
};

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 }) =&gt; {
  const [childVisible, setChildVisiblity] = useState(false);
  const hasChild = node.children &amp;&amp; node.children.length &gt; 0;

  const nodeStyle = level === 1 ? { fontWeight: &quot;bold&quot;, color: &quot;red&quot; } : {};

  return (
    &lt;li className=&quot;d-tree-node border-0&quot;&gt;
      &lt;div className=&quot;d-flex&quot; onClick={(e) =&gt; setChildVisiblity((v) =&gt; !v)}&gt;
        &lt;div className=&quot;col d-tree-head&quot; style={nodeStyle}&gt;
          {node.label}
        &lt;/div&gt;
      &lt;/div&gt;

      {hasChild &amp;&amp; childVisible &amp;&amp; (
        &lt;div className=&quot;d-tree-content&quot;&gt;
          &lt;ul className=&quot;d-flex d-tree-container flex-column&quot;&gt;
            {node.children.map((item) =&gt; (
              &lt;TreeNode key={item.key} node={item} level={level + 1} /&gt;
            ))}
          &lt;/ul&gt;
        &lt;/div&gt;
      )}
    &lt;/li&gt;
  );
};

<!-- begin snippet: js hide: false console: true babel: true -->

<!-- language: lang-js -->

const data = {  &quot;Category 1&quot;: [    {      key: &quot;1&quot;,      label: &quot;Applications&quot;,      children: [        {          key: &quot;3&quot;,          label: &quot;Browser&quot;,          children: [            {              key: &quot;4&quot;,              label: &quot;Mozilla&quot;,              children: []            },            {              key: &quot;5&quot;,              label: &quot;Firefox&quot;,              children: []            }          ]        }      ]   }  ],  &quot;Category 2&quot;: [    {      key: &quot;2&quot;,      label: &quot;OS&quot;,      children: [        {          key: &quot;6&quot;,          label: &quot;Windows&quot;,          children: []        }      ]    }  ]};
const TreeNode = ({ node, level = 1 }) =&gt; {
const [childVisible, setChildVisiblity] = React.useState(false);
const hasChild = node.children &amp;&amp; node.children.length &gt; 0;
const nodeStyle = level === 1 ? { fontWeight: &quot;bold&quot;, color: &quot;red&quot; } : {};
return (
&lt;li className=&quot;d-tree-node border-0&quot;&gt;
&lt;div className=&quot;d-flex&quot; onClick={(e) =&gt; setChildVisiblity((v) =&gt; !v)}&gt;
{hasChild &amp;&amp; (
&lt;div
className={`d-inline d-tree-toggler ${
childVisible ? &quot;active&quot; : &quot;&quot;
}`}
&gt;
{&#39;&gt;&#39;}
&lt;/div&gt;
)}
&lt;div className=&quot;col d-tree-head&quot; style={nodeStyle}&gt;
{node.label}
&lt;/div&gt;
&lt;/div&gt;
{hasChild &amp;&amp; childVisible &amp;&amp; (
&lt;div className=&quot;d-tree-content&quot;&gt;
&lt;ul className=&quot;d-flex d-tree-container flex-column&quot;&gt;
{node.children.map((item) =&gt; (
&lt;TreeNode key={item.key} node={item} level={level + 1} /&gt;
))}
&lt;/ul&gt;
&lt;/div&gt;
)}
&lt;/li&gt;
);
};
const Tree = ({ data = [] }) =&gt; {
return (
&lt;div className=&quot;d-tree&quot;&gt;
&lt;ul className=&quot;d-flex d-tree-container flex-column&quot;&gt;
{Object.entries(data).map(([category, items]) =&gt; (
&lt;TreeNode
key={category}
node={{ label: category, children: items }}
/&gt;
))}
&lt;/ul&gt;
&lt;/div&gt;
);
};
const TreeList = () =&gt; {
return &lt;Tree data={data} /&gt;;
};
ReactDOM.render(&lt;TreeList /&gt;, document.querySelector(&#39;.app&#39;));

<!-- 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 -->

&lt;script crossorigin src=&quot;https://unpkg.com/react@16/umd/react.development.js&quot;&gt;&lt;/script&gt;
&lt;script crossorigin src=&quot;https://unpkg.com/react-dom@16/umd/react-dom.development.js&quot;&gt;&lt;/script&gt;
&lt;div class=&#39;app&#39;&gt;&lt;/div&gt;

<!-- end snippet -->

使用Object.entries根据数据渲染层次结构。

huangapple
  • 本文由 发表于 2023年4月1日 01:17:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75901134.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定