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

相关推荐
光影少年13 小时前
react批量更新、同步/异步更新场景
前端·react.js·掘金·金石计划
假如让我当三天老蒯13 小时前
模块化:ES Module 与 CommonJS 的区别
前端·面试
用户409501157731713 小时前
Private Forge v2.0 发布:12大前端业务场景技能系统
前端
weedsfly14 小时前
异步编程全景与事件循环——彻底搞懂 JS 执行机制
前端·javascript
用户0595401744614 小时前
AI Agent记忆测试踩坑实录:Mock骗了我一周,Mem0+pytest一招破局
前端·css
用户17335980753714 小时前
纯前端 PDF 数字签名实战:Vue 3 + pdf-lib 在浏览器里完成签名嵌入
前端·javascript
IT_陈寒15 小时前
SpringBoot自动配置的坑,我爬了三天才出来
前端·人工智能·后端
Avan_菜菜1 天前
AI 能写代码了,为什么我反而开始要求它先写文档?
前端·github·ai编程
JieE2121 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2121 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法