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

如何在React中展示从接口获取的JSON树形结构数据?

解决React中多级树形地区展示的方案

步骤1:获取并转换后端数据

先通过axios请求接口,再将扁平的键值对数据转换为嵌套的树形结构,这是实现多级展示的核心。

import axios from 'axios';
import { useEffect, useState } from 'react';

const Nodes = () => {
  const [treeData, setTreeData] = useState([]);

  useEffect(() => {
    const fetchAndTransformData = async () => {
      try {
        const { data: rawData } = await axios.get('http://127.0.0.1:5000/nodes');
        const tree = buildNestedTree(rawData);
        setTreeData(tree);
      } catch (err) {
        console.error('数据获取失败:', err);
      }
    };

    fetchAndTransformData();
  }, []);

  // 核心:将扁平数据转为树形结构(适配层级路径格式,如"欧洲.德国.柏林")
  const buildNestedTree = (rawData) => {
    const nodeMap = {};
    const rootNodes = [];

    // 先把所有地区转为节点对象
    Object.entries(rawData).forEach(([name, fullPath]) => {
      nodeMap[name] = { name, children: [] };
      const pathSegments = fullPath.split('.');

      // 根节点(路径只有一级)直接加入根列表
      if (pathSegments.length === 1) {
        rootNodes.push(nodeMap[name]);
      } else {
        // 找到父节点的名称(路径去掉最后一段)
        const parentPath = pathSegments.slice(0, -1).join('.');
        const parentName = Object.keys(rawData).find(key => rawData[key] === parentPath);
        if (parentName) {
          nodeMap[parentName].children.push(nodeMap[name]);
        }
      }
    });

    return rootNodes;
  };

  // 递归渲染树形结构
  const renderTree = (nodes) => {
    return nodes.map(node => (
      <div key={node.name} style={{ marginLeft: 24 }}>
        <div>{node.name}</div>
        {node.children.length > 0 && renderTree(node.children)}
      </div>
    ));
  };

  return <div className="tree-container">{renderTree(treeData)}</div>;
};

export default Nodes;

步骤2:适配数字层级格式

如果后端返回的层级编号是数字格式(如"0"、"0.0"、"0.0.0"),修改buildNestedTree函数即可:

const buildNestedTree = (rawData) => {
  // 按层级深度排序,确保先处理父节点
  const sortedNodes = Object.entries(rawData)
    .map(([name, levelStr]) => ({
      name,
      levels: levelStr.split('.').map(Number),
      children: []
    }))
    .sort((a, b) => a.levels.length - b.levels.length);

  const nodeMap = {};
  const rootNodes = [];

  sortedNodes.forEach(node => {
    nodeMap[node.name] = node;
    if (node.levels.length === 1) {
      rootNodes.push(node);
    } else {
      // 匹配父节点的层级路径
      const parentLevelStr = node.levels.slice(0, -1).join('.');
      const parentNode = sortedNodes.find(n => n.levels.join('.') === parentLevelStr);
      if (parentNode) parentNode.children.push(node);
    }
  });

  return rootNodes;
};

步骤3:添加折叠/展开交互

如果需要节点的折叠功能,封装一个TreeItem组件:

const TreeItem = ({ node }) => {
  const [isExpanded, setIsExpanded] = useState(true);

  return (
    <div style={{ marginLeft: 24 }}>
      <div 
        onClick={() => setIsExpanded(!isExpanded)} 
        style={{ cursor: 'pointer', display: 'flex', gap: 8 }}
      >
        {node.children.length > 0 && (isExpanded ? '▼' : '▶')}
        <span>{node.name}</span>
      </div>
      {isExpanded && node.children.map(child => (
        <TreeItem key={child.name} node={child} />
      ))}
    </div>
  );
};

// 替换原renderTree函数
const renderTree = (nodes) => {
  return nodes.map(node => <TreeItem key={node.name} node={node} />);
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 15:18:03