关于 react-flow-architecture
react-flow-architecture 是面向 React Flow 应用规划的开发技能,帮助设计节点交互、规模策略、状态管理与架构,适用于节点式编辑器和工作流。
主要功能
- 01将交互映射到 React Flow 回调
- 02按节点数量选择策略
- 03比较本地与外部状态管理
- 04规划嵌套节点和视口持久化
- 05评估替代方案与渲染取舍
适用场景
- 01规划可视化工作流构建器
- 02为流程编辑器选择状态管理方案
- 03评估图规模增长时的渲染策略
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ existential-birds/ beagle --skill react-flow-architecture安装后在 Claude Code 中输入/react-flow-architecture确认已加载。
详细介绍
React Flow 架构
何时使用 React Flow
适用场景
- 可视化编程界面
- 工作流构建器和自动化工具
- 图表编辑器(流程图、组织结构图)
- 数据管道可视化
- 思维导图工具
- 基于节点的音频/视频编辑器
- 决策树构建器
- 状态机设计器
考虑其他方案
- 简单的静态图表(直接使用 SVG 或 canvas)
- 高强度实时协作(可能需要自定义同步层)
- 3D 可视化(使用 Three.js、react-three-fiber)
- 包含 1 万个以上节点的图分析(使用基于 WebGL 的方案,例如 Sigma.js)
决策工作流(关卡)
在确定技术栈或开始实施前,按以下顺序执行此流程。仅临时原型可跳过。
-
列出交互 — 列出主要用户操作(例如拖动、连接、删除、分组)。**通过标准:**每项操作都对应一个要实现的具体 React Flow 回调(
onNodesChange、onConnect等)。 -
评估规模 — 估算峰值节点数(可见画布节点数或文档总节点数)。**通过标准:**估算范围符合 节点数量指南 中的一行,并接受其中列出的策略(例如该行要求启用
onlyRenderVisibleElements时)。 -
确定状态位置 — 选择本地钩子、外部存储或 Redux/其他方案。**通过标准:**用一句话说明持久化、撤销或跨界面同步将在哪里实现,或明确写明“暂时不需要”。
-
重新评估其他方案 — 如果用例符合 考虑其他方案 中的情况,**通过标准:**用一句话说明 React Flow 仍然适用的原因,或说明改用的其他方案。
架构模式
Package 结构(xyflow)
@xyflow/system (vanilla TypeScript)
├── Core algorithms (edge paths, bounds, viewport)
├── xypanzoom (d3-based pan/zoom)
├── xydrag, xyhandle, xyminimap, xyresizer
└── Shared types
@xyflow/react (depends on @xyflow/system)
├── React components and hooks
├── Zustand store for state management
└── Framework-specific integrations
@xyflow/svelte (depends on @xyflow/system)
└── Svelte components and stores
**影响:**核心逻辑与框架无关。贡献代码或调试时,请确认问题是否出在 @xyflow/system 或特定框架的 package 中。
状态管理方案
1. 本地状态(简单应用)
// useNodesState/useEdgesState for prototyping
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
**优点:**简单,样板代码极少 **缺点:**状态局限于组件树
2. 外部存储(生产环境)
// Zustand store example
import { create } from 'zustand';
interface FlowStore {
nodes: Node[];
edges: Edge[];
setNodes: (nodes: Node[]) => void;
onNodesChange: OnNodesChange;
}
const useFlowStore = create<FlowStore>((set, get) => ({
nodes: initialNodes,
edges: initialEdges,
setNodes: (nodes) => set({ nodes }),
onNodesChange: (changes) => {
set({ nodes: applyNodeChanges(changes, get().nodes) });
},
}));
// In component
function Flow() {
const { nodes, edges, onNodesChange } = useFlowStore();
return <ReactFlow nodes={nodes} onNodesChange={onNodesChange} />;
}
**优点:**可在任何位置访问状态,更容易实现持久化/同步 **缺点:**需要更多设置,并且需要谨慎优化选择器
3. Redux/其他状态库
// Connect via selectors
const nodes = useSelector(selectNodes);
const dispatch = useDispatch();
const onNodesChange = useCallback((changes: NodeChange[]) => {
dispatch(nodesChanged(changes));
}, [dispatch]);
数据流架构
User Input → Change Event → Reducer/Handler → State Update → Re-render
↓
[Drag node] → onNodesChange → applyNodeChanges → setNodes → ReactFlow
↓
[Connect] → onConnect → addEdge → setEdges → ReactFlow
↓
[Delete] → onNodesDelete → deleteElements → setNodes/setEdges → ReactFlow
子流模式(嵌套节点)
// Parent node containing child nodes
const nodes = [
{
id: 'group-1',
type: 'group',
position: { x: 0, y: 0 },
style: { width: 300, height: 200 },
},
{
id: 'child-1',
parentId: 'group-1', // Key: parent reference
extent: 'parent', // Key: constrain to parent
position: { x: 10, y: 30 }, // Relative to parent
data: { label: 'Child' },
},
];
注意事项:
- 使用
extent: 'parent'限制拖动范围 - 使用
expandParent: true自动扩展父节点 - 父节点的 z-index 会影响子节点的渲染顺序
视口持久化
// Save viewport state
const { toObject, setViewport } = useReactFlow();
const handleSave = () => {
const flow = toObject();
// flow.nodes, flow.edges, flow.viewport
localStorage.setItem('flow', JSON.stringify(flow));
};
const handleRestore = () => {
const flow = JSON.parse(localStorage.getItem('flow'));
setNodes(flow.nodes);
setEdges(flow.edges);
setViewport(flow.viewport);
};
集成模式
与后端/API 集成
// Load from API
useEffect(() => {
fetch('/api/flow')
.then(r => r.json())
.then(({ nodes, edges }) => {
setNodes(nodes);
setEdges(edges);
});
}, []);
// Debounced auto-save
const debouncedSave = useMemo(
() => debounce((nodes, edges) => {
fetch('/api/flow', {
method: 'POST',
body: JSON.stringify({ nodes, edges }),
});
}, 1000),
[]
);
useEffect(() => {
debouncedSave(nodes, edges);
}, [nodes, edges]);
与布局算法集成
import dagre from 'dagre';
function getLayoutedElements(nodes: Node[], edges: Edge[]) {
const g = new dagre.graphlib.Graph();
g.setGraph({ rankdir: 'TB' });
g.setDefaultEdgeLabel(() => ({}));
nodes.forEach((node) => {
g.setNode(node.id, { width: 150, height: 50 });
});
edges.forEach((edge) => {
g.setEdge(edge.source, edge.target);
});
dagre.layout(g);
return {
nodes: nodes.map((node) => {
const pos = g.node(node.id);
return { ...node, position: { x: pos.x, y: pos.y } };
}),
edges,
};
}
性能扩展
节点数量指南
| 节点数 | 策略 |
|---|---|
| < 100 | 默认设置 |
| 100-500 | 启用 onlyRenderVisibleElements |
| 500-1000 | 简化自定义节点,减少 DOM 元素 |
| > 1000 | 考虑虚拟化、WebGL 替代方案 |
优化技巧
<ReactFlow
// Only render nodes/edges in viewport
onlyRenderVisibleElements={true}
// Reduce node border radius (improves intersect calculations)
nodeExtent={[[-1000, -1000], [1000, 1000]]}
// Disable features not needed
elementsSelectable={false}
panOnDrag={false}
zoomOnScroll={false}
/>
权衡
受控与非受控
| 受控 | 非受控 |
|---|---|
| 更多样板代码 | 代码更少 |
| 完全控制状态 | 内部状态 |
| 易于持久化 | 需要 toObject() |
| 更适合复杂应用 | 适合原型 |
连接模式
| 严格(默认) | 宽松 |
|---|---|
| 仅源端 → 目标端 | 任意连接点 → 任意连接点 |
| 行为可预测 | 更灵活 |
| 用于数据流 | 用于图表 |
<ReactFlow connectionMode={ConnectionMode.Loose} />
边的渲染
| 默认边 | 自定义边 |
|---|---|
| 渲染快速 | 控制更多 |
| 样式有限 | 支持任意 SVG/HTML |
| 适用于简单场景 | 适用于复杂标签 |
评论
支持 Markdown