如何为含静态JSON数据的react-table v7实现懒加载展开行
实现react-table v7已有数据的懒加载展开行
核心思路
你的数据已预获取完成,无需动态请求,只需在父行被点击展开时,才将对应子数据注入表格数据中,而非初始渲染所有层级数据。核心是借助react-table的展开API,结合自定义数据管理逻辑,控制子数据的加载时机。
具体实现步骤
- 预处理原始数据
给每个父节点添加hasChildren标识,同时将子数据从父节点中剥离,用Map存储父节点ID与子数据的对应关系,避免初始渲染时加载所有子节点:
// 示例预处理逻辑 const parentChildrenMap = new Map(); const processedData = originalData.map(item => { if (item.children?.length) { parentChildrenMap.set(item.id, item.children); return { ...item, children: undefined, hasChildren: true }; } return item; });
- 拦截展开事件注入子数据
通过react-table的hooks拦截行展开动作,当父行被展开时,从Map中取出对应子数据并添加到该行:
const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, } = useTable( { columns, data: processedData, initialState: { expanded: {} }, }, useExpanded, hooks => { hooks.useInstance.push(instance => { const originalToggleRowExpanded = instance.toggleRowExpanded; instance.toggleRowExpanded = (path, isExpanded) => { const targetRow = instance.rows.find(r => r.path === path); if (targetRow?.original.hasChildren && isExpanded) { const childrenData = parentChildrenMap.get(targetRow.original.id); targetRow.setSubRows(childrenData); } originalToggleRowExpanded(path, isExpanded); }; }); } );
- 自定义展开按钮显示逻辑
在列定义中,仅对含子节点的行显示展开按钮:
const columns = [ { id: 'expand', Header: () => null, Cell: ({ row }) => row.original.hasChildren ? ( <span {...row.getToggleRowExpandedProps()}> {row.isExpanded ? '▼' : '▶'} </span> ) : null, }, // 其他列定义... ];
- 性能优化补充
用useMemo缓存处理后的数据和列定义,避免不必要的重渲染;若数据量极大,可配合虚拟滚动库(如react-window)进一步减少DOM节点数量。
多层级展开适配
若需支持多层级嵌套,只需递归遍历原始数据,给每一层的父节点都添加hasChildren标识,并将子数据存入Map即可,展开逻辑无需额外修改。
内容的提问来源于stack exchange,提问作者Yashwant Raut
相关产品推荐
相关产品推荐

