React 网络图表当前节点无API数据时加载前一节点内容的实现问题
解决方案
核心逻辑是新增节点访问历史栈记录跳转路径,空数据返回时从历史栈回溯到上一个有效节点,同时补充原有代码缺失的实例销毁逻辑避免内存泄漏,修改后代码如下:
const NetworkGraph = (props: any) => { const container = useRef<HTMLInputElement | null>(null); const networkRef = useRef<Network | null>(null); // 存储network实例用于销毁 const [nodeId, setNodeId] = useState(props.nodeId); // 新增历史栈,初始存储根节点ID const [nodeHistory, setNodeHistory] = useState<number[] | string[]>([props.nodeId]); const { graphData, isLoading } = useGetNetowrkGraphData(nodeId); // 自定义hook发起API请求 useEffect(() => { if (isLoading === false) { if (graphData.nodes.length <= 0) { setMessage('No data found', 'error'); // 回退逻辑:历史栈长度大于1时才回退,避免误删初始根节点 if (nodeHistory.length > 1) { // 移除最后一个无效节点ID const newHistory = nodeHistory.slice(0, -1); setNodeHistory(newHistory); // 回退到上一个有效节点 setNodeId(newHistory[newHistory.length - 1]); // 直接返回,无需渲染当前无效数据对应的图表 return; } } const nodes = new DataSet(graphData.nodes); const edges = new DataSet(graphData.edges as any[]); const networkData = { nodes: nodes, edges: edges }; // 销毁之前的实例避免重复渲染和内存泄漏 if (networkRef.current) { networkRef.current.destroy(); } // 新实例存入ref networkRef.current = container.current && new Network(container.current, networkData, options); networkRef.current?.on('doubleClick', function (params) { var ids = params.nodes; var clickedNodes = nodes.get(ids); if (clickedNodes && clickedNodes.length > 0) { const newNodeId = clickedNodes[0].id; setNodeId(newNodeId); // 新节点加入历史栈 setNodeHistory(prev => [...prev, newNodeId]); } }); } // 组件卸载时销毁实例 return () => { if (networkRef.current) { networkRef.current.destroy(); } } }, [ container, nodeId, graphData.nodes, graphData.edges, isLoading, setNodeId, setMessage, nodeHistory, ]); if (isLoading) return <div>Loading...</div>; return ( <> <Div> <div ref={container}/> </Div> </> ); }; export default NetworkGraph;
如果需要支持浏览器返回键回退节点,可以进一步将历史栈和浏览器history API绑定,无需修改现有核心逻辑。
内容的提问来源于stack exchange,提问作者Rasik Jain
相关产品推荐
相关产品推荐

