如何在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
相关产品推荐
相关产品推荐

