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

相关推荐
guygg882 小时前
NSGA-II自定义优化函数MATLAB实现
开发语言·matlab
三翼鸟数字化技术团队2 小时前
前端水印实现方案
前端
杜子不疼.2 小时前
Python多模态AI开发指南:让AI同时理解文字、图片和语音
开发语言·人工智能·python
IT_陈寒2 小时前
SpringBoot自动配置的坑把我埋了半小时
前端·人工智能·后端
专注VB编程开发20年2 小时前
VBA/VB6连接、读取Mdb access数据库最快的方法
前端·ui·ado·vb6
逻辑驱动的ken2 小时前
Java高频面试考点04
java·开发语言·算法·哈希算法·散列表
小饕2 小时前
RAG学习之 - 检索质量评估指标详解:从概念到代码实战
开发语言·人工智能·python·学习
John.Lewis2 小时前
C++加餐课-继承和多态:扩展学习
开发语言·c++·笔记
XMYX-02 小时前
12 - Go Slice:底层原理、扩容机制与常见坑位
开发语言·golang