React Flow新增节点无法连接且拖拽触发初始化警告问题
React Flow 新增节点无法连接且拖拽警告的解决方案
在使用React Flow构建节点图时,点击按钮新增节点后,节点无法与其他节点建立连接,拖拽该节点时控制台出现以下警告:
It seems that you are trying to drag a node that is not initialized.
Please use onNodesChange as explained in the docs.
用户的原始代码如下:
import React, { useState, useCallback, useEffect, useRef } from 'react'; import { ReactFlow, Background, Controls, ReactFlowProvider, addEdge, useNodesState, useEdgesState, useReactFlow, applyNodeChanges, useUpdateNodeInternals } from '@xyflow/react'; import './PageEditRoute.css'; import '@xyflow/react/dist/style.css'; const defaultlNodes = [ { id: '1', data: { label: 'Старт' }, position: { x: 100, y: 50 }, type: 'input', }, { id: '2', data: { label: 'Финиш' }, position: { x: 100, y: 400 }, type: 'output', }, { id: '3', data: { label: 'Просто узел' }, position: { x: 100, y: 150 }, type: 'default', }, ]; const defaultEdges = [ { id: '1-2', source: '1', target: '3' }, ]; function Flow() { const { addNodes } = useReactFlow(); const [nodes, setNodes, onNodesChange] = useNodesState(defaultlNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(defaultEdges); const onClick = useCallback(() => { const id = Math.floor(Math.random() * 10000); const newNode = { id, draggable: true, selectable: true, connectable: true, deletable: true, position: { x: 100, y: 250, }, data: { label: `Node ${id}`, }, style: { visibility: "visible", } }; addNodes(newNode); }, [addNodes]); const onConnect = useCallback( (params) => setEdges((eds) => addEdge(params, eds)), [], ); return ( <> <button onClick={onClick} className="btn-add">add node</button> <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} fitView /> </> ); } export default function PageEditRoute(){ return( <div style={{ height: '80%'}}> <ReactFlowProvider> <Flow /> </ReactFlowProvider> </div> ); }
问题根源
- 状态不同步:使用
useReactFlow提供的addNodes方法添加节点,只会更新React Flow内部的节点状态,但不会同步更新组件通过useNodesState维护的nodes数组,导致组件状态与React Flow内部状态不一致,触发拖拽警告。 - 缺少节点类型:新增的节点未设置
type属性,默认不会生成连接手柄,因此无法建立连接。 - 依赖缺失:
onConnect回调的依赖数组为空,未包含setEdges,可能导致闭包问题。
修复步骤
1. 改用setNodes添加节点
移除useReactFlow的addNodes,直接通过useNodesState返回的setNodes来更新节点数组,确保组件状态与React Flow内部状态同步:
// 移除这一行:const { addNodes } = useReactFlow(); const onClick = useCallback(() => { const id = Math.floor(Math.random() * 10000).toString(); // 推荐使用字符串ID const newNode = { id, type: 'default', // 添加节点类型,确保生成连接手柄 draggable: true, selectable: true, connectable: true, deletable: true, position: { x: 100, y: 250 }, data: { label: `Node ${id}` }, style: { visibility: "visible" } }; // 使用函数式更新,基于最新节点数组添加新节点 setNodes(prevNodes => [...prevNodes, newNode]); }, [setNodes]);
2. 修复onConnect的依赖数组
将setEdges添加到onConnect的依赖数组中,避免闭包导致的状态更新异常:
const onConnect = useCallback( (params) => setEdges((eds) => addEdge(params, eds)), [setEdges], // 添加setEdges作为依赖 );
3. 可选:优化容器高度
将页面容器的高度单位改为vh,确保React Flow能正确获取可用空间:
// PageEditRoute组件中的容器样式 <div style={{ height: '80vh'}}>
修改后的完整Flow组件
import React, { useCallback } from 'react'; import { ReactFlow, Background, Controls, ReactFlowProvider, addEdge, useNodesState, useEdgesState, } from '@xyflow/react'; import './PageEditRoute.css'; import '@xyflow/react/dist/style.css'; const defaultlNodes = [ { id: '1', data: { label: 'Старт' }, position: { x: 100, y: 50 }, type: 'input', }, { id: '2', data: { label: 'Финиш' }, position: { x: 100, y: 400 }, type: 'output', }, { id: '3', data: { label: 'Просто узел' }, position: { x: 100, y: 150 }, type: 'default', }, ]; const defaultEdges = [ { id: '1-2', source: '1', target: '3' }, ]; function Flow() { const [nodes, setNodes, onNodesChange] = useNodesState(defaultlNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(defaultEdges); const onClick = useCallback(() => { const id = Math.floor(Math.random() * 10000).toString(); const newNode = { id, type: 'default', draggable: true, selectable: true, connectable: true, deletable: true, position: { x: 100, y: 250, }, data: { label: `Node ${id}`, }, style: { visibility: "visible", } }; setNodes(prevNodes => [...prevNodes, newNode]); }, [setNodes]); const onConnect = useCallback( (params) => setEdges((eds) => addEdge(params, eds)), [setEdges], ); return ( <> <button onClick={onClick} className="btn-add">add node</button> <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} fitView > <Background /> <Controls /> </ReactFlow> </> ); } export default function PageEditRoute(){ return( <div style={{ height: '80vh'}}> <ReactFlowProvider> <Flow /> </ReactFlowProvider> </div> ); }
内容的提问来源于stack exchange,提问作者Михаил Дьяченко
相关产品推荐
相关产品推荐

