You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
    );
    
}

问题根源

  1. 状态不同步:使用useReactFlow提供的addNodes方法添加节点,只会更新React Flow内部的节点状态,但不会同步更新组件通过useNodesState维护的nodes数组,导致组件状态与React Flow内部状态不一致,触发拖拽警告。
  2. 缺少节点类型:新增的节点未设置type属性,默认不会生成连接手柄,因此无法建立连接。
  3. 依赖缺失: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,提问作者Михаил Дьяченко

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 12:55:58