You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS与Material UI TreeView如何渲染不同字段名多层JSON数据

问题场景

你需要将多层嵌套、各层级子节点对应字段名不一致的对象数组传入TreeView组件实现层级展示,原始数据结构如下:

export const application_group_one = [
    {
        id: uniqueId(),
        name: "Application 1",
        organizations: [
            {
                id: uniqueId(),
                name: "Organization 1",
                artifacts: [
                    {
                        id: uniqueId(),
                        name: "Artifact 1",
                    },
                ],
            },
        ],
    },
    {
        id: uniqueId(),
        name: "Application 2",
        organizations: [
            {
                id: uniqueId(),
                name: "Organization 1",
                artifacts: [],
            },
        ],
    },
];

export const application_group_two = [
    {
        id: uniqueId(),
        name: "Application 3",
        organizations: [
            {
                id: uniqueId(),
                name: "Organization 1",
                artifacts: [
                    {
                        id: uniqueId(),
                        name: "Artifact 1",
                    },
                    {
                        id: uniqueId(),
                        name: "Artifact 2",
                    },
                    {
                        id: uniqueId(),
                        name: "Artifact 3",
                    },
                ],
            },
            {
                id: uniqueId(),
                name: "Organization 2",
                artifacts: [
                    {
                        id: uniqueId(),
                        name: "Artifact 1",
                    },
                    {
                        id: uniqueId(),
                        name: "Artifact 2",
                    },
                    {
                        id: uniqueId(),
                        name: "Artifact 3",
                    },
                ],
            },
            {
                id: uniqueId(),
                name: "Organization 3",
                artifacts: [
                    {
                        id: uniqueId(),
                        name: "Artifact 1",
                    },
                    {
                        id: uniqueId(),
                        name: "Artifacy 2",
                    },
                    {
                        id: uniqueId(),
                        name: "Artifact 3",
                    },
                ],
            },
            {
                id: uniqueId(),
                name: "Organization 4",
                artifacts: [
                    {
                        id: uniqueId(),
                        name: "Artifact 1",
                    },
                    {
                        id: uniqueId(),
                        name: "Artifact 2",
                    },
                    {
                        id: uniqueId(),
                        name: "Artifact 3",
                    },
                ],
            },
        ],
    },
];

现有实现仅能正常渲染Organizations层级,无法展示artifacts层级,原有代码如下:

const getTreeItemsFromData = (treeItems) => {
    return treeItems.map((treeItemData) => {
        let organizations = undefined;
        if (treeItemData.organizations && treeItemData.organizations.length > 0) {
            organizations = getTreeItemsFromData(treeItemData.organizations);
        }
        return <TreeItem key={treeItemData.id} nodeId={treeItemData.id} label={treeItemData.name} children={organizations} />;
    });
};
const DataTreeView = ({ treeItems }) => {
    return (
        <TreeView defaultCollapseIcon={<ExpandMoreIcon />} defaultExpandIcon={<ChevronRightIcon />}>
            {getTreeItemsFromData(treeItems)}
        </TreeView>
    );
};

export const Tree = () => {
    return (
        <div className="App">
            <DataTreeView treeItems={application_group_one} />
            <br />
            <DataTreeView treeItems={application_group_two} />
        </div>
    );
};
问题根因

原有递归逻辑硬编码了子节点字段名为organizations,没有对artifacts字段做处理,这种硬编码字段名的写法既无法覆盖现有三层结构的渲染需求,也不能兼容后续新增层级的场景。

修复方案

放弃硬编码子节点字段名的写法,通过通用特征自动识别节点下的子节点集合:只要是当前节点属性中值为非空数组、且数组元素包含id和name字段,就判定为子节点列表,传入递归逻辑渲染即可。
修复后的完整代码如下:

const getTreeItemsFromData = (treeItems) => {
    return treeItems.map((treeItemData) => {
        let children = undefined;
        // 遍历当前节点所有属性,自动识别子节点数组
        Object.values(treeItemData).forEach(val => {
            if (
                Array.isArray(val) 
                && val.length > 0 
                && typeof val[0] === 'object'
                && 'id' in val[0] 
                && 'name' in val[0]
            ) {
                children = getTreeItemsFromData(val);
            }
        });
        return <TreeItem key={treeItemData.id} nodeId={treeItemData.id} label={treeItemData.name} children={children} />;
    });
};

const DataTreeView = ({ treeItems }) => {
    return (
        <TreeView defaultCollapseIcon={<ExpandMoreIcon />} defaultExpandIcon={<ChevronRightIcon />}>
            {getTreeItemsFromData(treeItems)}
        </TreeView>
    );
};

export const Tree = () => {
    return (
        <div className="App">
            <DataTreeView treeItems={application_group_one} />
            <br />
            <DataTreeView treeItems={application_group_two} />
        </div>
    );
};
方案特性
  • 无需提前声明各层级子节点的字段名,自动适配organizations、artifacts等任意命名的子节点字段
  • 支持无限层级嵌套,后续如果在artifacts下新增versions、builds等层级,不需要修改渲染逻辑即可直接展示
  • 兼容原有代码的使用方式,不需要修改传入的数据源结构
  • 如果业务场景中存在单个节点下挂载多个子节点数组的情况,可以调整子节点识别逻辑,将多个符合条件的数组合并后再传入递归即可。

内容的提问来源于stack exchange,提问作者Drew Pepin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 20:43:10