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

相关推荐
IT笔记18 分钟前
【Rust】Rust Match 模式匹配详解
java·开发语言·rust
kyriewen27 分钟前
我扒了 GPT-5.6 的全部编程跑分——有一项 OpenAI 没敢放出来
前端·gpt·ai编程
逝水无殇39 分钟前
C# 运算符重载详解
开发语言·后端·c#
前端H1 小时前
微前端 v3 架构升级:从加载隔离到状态协同
前端·架构·状态模式
TPBoreas1 小时前
配置信息防泄露方案:.env 环境隔离详解(dotenv-java)
java·开发语言
山河木马1 小时前
GPU自动处理专题3-NDC怎么映射成屏幕像素坐标(视口变换)
javascript·webgl·图形学
敲代码的嘎仔2 小时前
实习日志day6--实习日志day6--title命名规范化&businessType纠正&补充缺失的@Log注解&报警与通信模块补充&产出阶段总结文档
java·开发语言·人工智能·git·python·实习·大二
江华森2 小时前
Python 实现高德地图找房(一):环境搭建与数据爬虫
开发语言·爬虫·python
杜子不疼.2 小时前
【Qt初识】信号槽(三):机制意义、断开连接与 Lambda 表达式
开发语言·数据库·qt
陆枫Larry2 小时前
小程序包体积优化:用 SVG 图片替换 iconfont,并保留 CSS 控色能力
前端