[特殊字符] React Flow 从入门到理解

🧠 一句话讲清 React Flow 是什么?

👉 React Flow 本质就是一个:

"帮你画流程图的 UI + 帮你收集用户操作的事件系统"

你可以把它想象成:

  • ReactFlow → 画布(Canvas)
  • nodes → 方块(节点)
  • edges → 连线
  • 用户操作 → 拖动 / 连接 / 删除
🏗 我们先看最核心代码👇
TypeScript 复制代码
import { useState, useCallback } from 'react';
import { ReactFlow, applyNodeChanges, applyEdgeChanges, addEdge } from '@xyflow/react';

const initialNodes = [
  { id: 'n1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } },
  { id: 'n2', position: { x: 0, y: 100 }, data: { label: 'Node 2' } },
];

const initialEdges = [{ id: 'n1-n2', source: 'n1', target: 'n2' }];

👉 nodes 是什么?

👉 就是节点数据源

javascript 复制代码
{
  id: 'n1',
  position: { x: 0, y: 0 },
  data: { label: 'Node 1' }
}

你可以理解为:

👉 "画布上每一个方块的描述信息"


👉 edges 是什么?

👉 就是连线数据源

javascript 复制代码
{
  id: 'n1-n2',
  source: 'n1',
  target: 'n2'
}

👉 表示:n1 → n2 有一条线


👉 ReactFlow 在干嘛?
TypeScript 复制代码
<ReactFlow nodes={nodes} edges={edges} />

👉 它只是:

👉 把你的数据渲染成 UI

⚠️ 重点来了:

👉 React Flow 自己不存数据!


🧠 核心认知(非常重要)

👉 React Flow = UI 渲染器

👉 nodes / edges = 你的数据

👉 onXXXChange = 数据变化入口

一句话总结:

👉 React Flow 是"无状态"的,一切由你控制


🔥 用户操作时到底发生了什么?

我们来看一个真实场景👇


🎬 场景:你拖动了一个节点

发生了什么?


🧩 Step 1:ReactFlow 捕获操作

👉 你拖动节点


🧩 Step 2:生成 change(关键!)

ReactFlow 会生成:

javascript 复制代码
{
  type: 'position',
  id: 'n1',
  position: { x: 100, y: 200 }
}

👉 这就是"变化描述"


🧩 Step 3:触发 onNodesChange
TypeScript 复制代码
onNodesChange(changes)

注意:

👉 changes 是一个数组!


🧩 Step 4:进入 applyNodeChanges
TypeScript 复制代码
setNodes(nodes => applyNodeChanges(changes, nodes))

🧩 Step 5:更新 state

👉 返回新的 nodes


🧩 Step 6:React 重新渲染

👉 UI 更新完成


🔥 核心一:applyNodeChanges 到底干了什么?

旧 nodes

↓

遍历 changes

↓

根据 type 修改 node

↓

返回新 nodes

TypeScript 复制代码
function applyNodeChanges(changes, nodes) {
  let nextNodes = [...nodes];

  changes.forEach(change => {
    switch (change.type) {
      case 'position':
        nextNodes = nextNodes.map(node =>
          node.id === change.id
            ? { ...node, position: change.position }
            : node
        );
        break;

      case 'remove':
        nextNodes = nextNodes.filter(node => node.id !== change.id);
        break;

      case 'select':
        nextNodes = nextNodes.map(node =>
          node.id === change.id
            ? { ...node, selected: change.selected }
            : node
        );
        break;

      // 还有其他类型...
    }
  });

  return nextNodes;
}
  1. position(拖动节点)2. remove(删除节点)3. select(选中节点)

🔥 核心二:applyEdgeChanges
🧠 一句话

👉 和 node 一模一样,只不过对象换成 edge

支持的操作:
  • remove(删除线)
  • select(选中线)
TypeScript 复制代码
function applyEdgeChanges(changes, edges) {
  let nextEdges = [...edges];

  changes.forEach(change => {
    switch (change.type) {
      case 'remove':
        nextEdges = nextEdges.filter(edge => edge.id !== change.id);
        break;

      case 'select':
        nextEdges = nextEdges.map(edge =>
          edge.id === change.id
            ? { ...edge, selected: change.selected }
            : edge
        );
        break;
    }
  });

  return nextEdges;
}

🔥 核心三:addEdge 到底做了什么?
🧠 触发时机

👉 用户拖一条线连接两个节点

🧩 Step 1:用户开始拖拽(还没触发 onConnect)

👉 从某个节点的 handle(小圆点)开始拖

此时内部状态

javascript 复制代码
{
  source: 'n1',
  // target 还没确定
}

👉 这时候还没有 Connection,也没有 Edge


🧩 Step 2:拖到目标节点上(关键时刻)

当你松开鼠标那一刻:

👉 React Flow 才会生成一个 Connection

javascript 复制代码
{
  source: 'n1',
  target: 'n2'
}

⚠️ 注意:

👉这里还没有 id

👉 还没有进入你的 edges state

🔥 Step 3:触发 onConnect(这里的params类型为 Connection)
javascript 复制代码
onConnect(params)

🧠 官方为什么写成 Edge | Connection?

因为:

👉 你可以自己传 Edge 进去

比如:

TypeScript 复制代码
onConnect={(params) => {
  const edge = {
    ...params,
    id: 'custom-id',
    animated: true,
  };
  setEdges((eds) => [...eds, edge]);
}}

👉 这时候你手动把 Connection → Edge


🔥 Step 4:addEdge 干了什么(本质转换)
TypeScript 复制代码
addEdge(params, edges)
🧠 addEdge 本质
TypeScript 复制代码
function addEdge(connection, edges) {
  const newEdge = {
    id: `${connection.source}-${connection.target}`, // 自动生成id
    source: connection.source,
    target: connection.target,
    ...connection, // 你的 type / animated 等
  };

  return [...edges, newEdge];
}
🎯 重点总结

👉 addEdge 就是:

👉 帮你生成一条"合法的边"并加进数组


🔗 一张图串起所有流程

用户操作(拖动 / 点击 / 连线)

↓

ReactFlow 捕获事件

↓

生成 changes / connection

↓

onNodesChange / onEdgesChange / onConnect

↓

applyNodeChanges / applyEdgeChanges / addEdge

↓

setState

↓

React 重新渲染

相关推荐
admin and root6 小时前
「AI安全篇」实战AntiDebug自动化JS逆向加解密MCP
javascript·人工智能·网络安全·自动化·漏洞挖掘·cnvd·src赏金
落魄实习生6 小时前
Agent Scope Java 2.x 系列【7】工具使用
java·开发语言·ai
前端snow6 小时前
ai agent --- postgreSQL 关系型数据库
前端
茉莉玫瑰花茶7 小时前
GO [ 方法 ]
开发语言·后端·golang
卷无止境7 小时前
ECharts:把数据变成故事的可视化利器
前端
Eric_见嘉7 小时前
在职前端 Skill 和 MCP 分享
前端·后端·agent
狗凯之家源码网7 小时前
微博图床 PHP 系统搭建与实战应用指南
android·开发语言·php
liangshanbo12158 小时前
面试题:如何优化 Webpack 的打包速度?
前端·webpack·node.js
wengad8 小时前
从 wangEditor 迁到 wangEditor-next
前端·javascript·vue.js
乌暮9 小时前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习