[特殊字符] 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 重新渲染

相关推荐
http阿拉丁神猫3 小时前
Go语言入门笔记:从基础到开发环境搭建(二)
开发语言·笔记·golang
不会就选b4 小时前
C++补充部分(一)--lambda 表达式
开发语言·c++
java1234_小锋4 小时前
【技术专题】HTML5 网页技术 - HTML5 Canvas 基础以及动画入门
前端·html·html5
Pniubi7 小时前
HashMap的扩容和树化边界
java·开发语言
知了学历孙老师7 小时前
小自考的校考和统考,出题方和难度差在哪
java·大数据·前端
gCode Teacher 格码致知8 小时前
Pandas教学-17:Series与Dataframe的关系
开发语言·python·pandas
发量惊人的中年网工8 小时前
分公司访问总部ERP慢怎么办?SD-WAN组网的排查与验收要点
服务器·开发语言·php
下页、再停留9 小时前
【C#桌面客户端系列学习-15】生成可视化图表之折线图、柱状图、饼状图
开发语言·c#
ShineWinsu9 小时前
对于JavaScript:操作元素的解析
开发语言·前端·javascript·面试·web·dom·元素
福兮说10 小时前
JSON 格式正确,数据就可靠吗?我用一份自编配置检查类型与空值
java·前端·json