在react-flow-renderer中如何验证所有节点都存在关联的连接边?
React Flow 保存前节点连接校验实现方案
核心逻辑
在触发流保存逻辑前,分为两层校验:
- 全量节点连接校验:检查所有节点是否符合业务要求的连接规则(比如输入节点必须有出边、普通节点必须同时有入边和出边等)
- 指定节点对校验:可自定义检查某几个节点之间是否存在对应方向的连接边,比如示例要求的2→3、3→4的连接
基础数据结构
// 参考的nodes和edges结构 const flowElements = [ { id: '1', type: 'input', data: { label: 'Node 1' }, position: { x: 250, y: 5 }, }, { id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 100 } }, { id: '3', data: { label: 'Node 3' }, position: { x: 400, y: 100 } }, { id: '4', data: { label: 'Node 4' }, position: { x: 400, y: 200 } }, { id: 'e1-2', source: '1', target: '2', }, //{ id: 'e1-3', source: '1', target: '3' }, ]; // 拆分节点和边 const nodes = flowElements.filter(el => !el.source && !el.target); const edges = flowElements.filter(el => el.source && el.target);
校验函数实现
// 预处理边的连接映射,提升查询效率 const edgeMap = new Set(edges.map(edge => `${edge.source}->${edge.target}`)); /** * 保存前校验函数 * @param {Array} requiredNodePairs 需校验的节点对,格式为[[源节点id, 目标节点id], ...] * @returns {Object} 校验结果,pass为是否通过,errorMsg为错误提示 */ const validateFlowBeforeSave = (requiredNodePairs = []) => { // 第一层:全量节点连接规则校验,可根据业务调整规则 for (const node of nodes) { const hasOutEdge = edges.some(edge => edge.source === node.id); const hasInEdge = edges.some(edge => edge.target === node.id); // 输入节点必须有出边 if (node.type === 'input' && !hasOutEdge) { return { pass: false, errorMsg: `输入节点${node.data.label || node.id}缺少输出连接` } } // 输出节点必须有入边,没有输出节点类型可以删掉这段 if (node.type === 'output' && !hasInEdge) { return { pass: false, errorMsg: `输出节点${node.data.label || node.id}缺少输入连接` } } // 普通节点必须至少有一条连接,允许孤立节点可以删掉这段 if (!node.type && !hasInEdge && !hasOutEdge) { return { pass: false, errorMsg: `节点${node.data.label || node.id}未连接任何边` } } } // 第二层:指定节点对连接校验 for (const [sourceId, targetId] of requiredNodePairs) { if (!edgeMap.has(`${sourceId}->${targetId}`)) { const sourceLabel = nodes.find(n => n.id === sourceId)?.data?.label || sourceId; const targetLabel = nodes.find(n => n.id === targetId)?.data?.label || targetId; return { pass: false, errorMsg: `缺少${sourceLabel}到${targetLabel}的连接` } } } return { pass: true, errorMsg: '' } }
保存&恢复功能示例
保存逻辑调用
const handleSave = () => { // 传入需要校验的节点对,比如要求2→3、3→4必须有连接 const validateRes = validateFlowBeforeSave([['2','3'], ['3','4']]); if (!validateRes.pass) { alert(validateRes.errorMsg); return; } // 校验通过后序列化流数据存到本地或者后端 const savedData = JSON.stringify({ nodes, edges }); localStorage.setItem('flowData', savedData); }
恢复逻辑调用
const restoreFlow = () => { const savedData = localStorage.getItem('flowData'); if (!savedData) return; const { nodes: savedNodes, edges: savedEdges } = JSON.parse(savedData); // 将解析后的savedNodes和savedEdges赋值给ReactFlow对应的状态即可 }
注意:可以根据业务需求自行修改校验规则,比如不需要全量节点校验直接删除对应代码段即可,不需要指定节点对校验传空数组即可。
内容的提问来源于stack exchange,提问作者Rai
相关产品推荐
相关产品推荐

