Skip to Content
教程故障排除迁移到 v12

迁移到 React Flow 12

🌐 Migrate to React Flow 12

你可以在这里找到旧版本 React Flow 的文档: v11 , v10 , v9 

在你可以使用 React Flow 12 提供的新功能(如 服务端渲染、计算流程和夜间模式)之前,你首先需要解决以下破坏性更改。我们尽量将破坏性更改保持到最低,但为了实现新功能,其中一些更改是必要的。

🌐 Before you can use the new features that come with React Flow 12 like server side rendering, computing flows, and dark mode, here are the breaking changes you’ll have to address first. We tried to keep the breaking changes to a minimum, but some of them were necessary to implement the new features.

迁移指南

🌐 Migration guide

在开始迁移之前,你需要安装新软件包。

🌐 Before you start to migrate, you need to install the new package.

npm install @xyflow/react

1. 一个新的 npm 包名称

🌐 1. A new npm package name

reactflow 已经重命名为 @xyflow/react,并且不再是默认导入。你还需要调整样式导入。在 v12 之前,React Flow 被分成多个包。现在不再是这样。如果你只是使用核心功能,现在需要安装 @xyflow/react 包。

🌐 The package reactflow has been renamed to @xyflow/react and it’s not a default import anymore. You also need to adjust the style import. Before v12, React Flow was divided into multiple packages. That’s not the case anymore. If you just used the core, you now need to install the @xyflow/react package.

旧 API

// npm install reactflow import ReactFlow from 'reactflow';

新 API

// npm install @xyflow/react import { ReactFlow } from '@xyflow/react'; // you also need to adjust the style import import '@xyflow/react/dist/style.css'; // or if you just want basic styles import '@xyflow/react/dist/base.css';

2. 节点 measured 属性用于测量的 widthheight

🌐 2. Node measured attribute for measured width and height

所有测量的节点值现在都存储在 node.measured 中。除了新的包名称,这是最大的变化。在 React Flow 测量你的节点后,它会将尺寸写入 node.measured.widthnode.measured.height。如果你正在使用任何布局库,如 dagre 或 elk,现在需要从 node.measured 获取尺寸,而不是 node。如果你使用 widthheight,这些值现在将用作内联样式来指定节点尺寸。

🌐 All measured node values are now stored in node.measured. Besides the new package name, this is the biggest change. After React Flow measures your nodes, it writes the dimensions to node.measured.width and node.measured.height. If you are using any layouting library like dagre or elk, you now need to take the dimensions from node.measured instead of node. If you are using width and height, those values will now be used as inline styles to specify the node dimensions.

旧 API

// getting the measured width and height const nodeWidth = node.width; const nodeHeight = node.height;

新 API

// getting the measured width and height const nodeWidth = node.measured?.width; const nodeHeight = node.measured?.height;

3. 新的尺寸处理 node.width / node.heightnode.measured.width / node.measured.height

🌐 3. New dimension handling node.width / node.height vs node.measured.width / node.measured.height

为了支持服务器端渲染,我们不得不对 API 进行一些重构,以便用户可以更轻松地传递节点尺寸。为此,我们更改了 node.widthnode.height 属性的行为。在 React Flow 11 中,这些属性是测量值,仅用作参考。在 React Flow 12 中,这些属性被用作内联样式来指定节点尺寸。如果你是从数据库加载节点,你可能需要从节点中移除 widthheight 属性,因为它们的行为现在略有不同。现在使用 widthheight 意味着节点尺寸不再根据内容动态变化,而是固定的。

🌐 In order to support server side rendering we had to restructure the API a bit, so that users can pass node dimensions more easily. For this we changed the behavior of the node.width and node.height attributes. In React Flow 11, those attributes were measured values and only used as a reference. In React Flow 12 those attributes are used as inline styles to specify the node dimensions. If you load nodes from a database, you probably want to remove the width and height attributes from your nodes, because the behavior is slightly different now. Using width and height now means that the dimensions are not dynamic based on the content but fixed.

旧 API

// in React Flow 11 you might have used node.style to set the dimensions const nodes = [ { id: '1', type: 'input', data: { label: 'input node' }, position: { x: 250, y: 5 }, style: { width: 180, height: 40 }, }, ];

新 API

// in React Flow 12 you can used node.width and node.height to set the dimensions const nodes = [ { id: '1', type: 'input', data: { label: 'input node' }, position: { x: 250, y: 5 }, width: 180, height: 40, }, ];

如果你想更多地了解如何为服务器端渲染配置 React Flow,你可以在服务器端渲染指南中阅读相关内容。

🌐 If you want to read more about how to configure React Flow for server side rendering, you can read about it in the server side rendering guide.

4. 更新节点和边

🌐 4. Updating nodes and edges

我们不再支持通过对象变更来更新节点和边。如果你想更新某个属性,你需要创建一个新的节点/边。

🌐 We are not supporting node and edge updates with object mutations anymore. If you want to update a certain attribute, you need to create a new node / edge.

旧 API

setNodes((currentNodes) => currentNodes.map((node) => { node.hidden = true; return node; }), );

新 API

setNodes((currentNodes) => currentNodes.map((node) => ({ ...node, hidden: true, })), );

🌐 5. Rename onEdgeUpdate (and related APIs) to onReconnect

我们将 onEdgeUpdate 函数重命名为 onReconnect,以及所有相关的 API(如下所述)。新名称更加具有描述性,并且明确表明该函数用于重新连接边。

🌐 We renamed the onEdgeUpdate function to onReconnect and all related APIs (mentioned below). The new name is more descriptive and makes it clear that the function is used to reconnect edges.

  • updateEdge 已重命名为 reconnectEdge
  • onEdgeUpdateStart 已重命名为 onReconnectStart
  • onEdgeUpdate 已重命名为 onReconnect
  • onEdgeUpdateEnd 已重命名为 onReconnectEnd
  • edgeUpdaterRadius 已重命名为 reconnectRadius
  • edge.updatable 已重命名为 edge.reconnectable
  • edgesUpdatable 已重命名为 edgesReconnectable

旧 API

<ReactFlow onEdgeUpdate={onEdgeUpdate} onEdgeUpdateStart={onEdgeUpdateStart} onEdgeUpdateEnd={onEdgeUpdateEnd} />

新 API

<ReactFlow onReconnect={onReconnect} onReconnectStart={onReconnectStart} onReconnectEnd={onReconnectEnd} />

6. 将 parentNode 重命名为 parentId

🌐 6. Rename parentNode to parentId

如果你正在使用子流程,你需要将 node.parentNode 重命名为 node.parentIdparentNode 属性有点误导,因为它不是父节点的引用,而是父节点的 id

🌐 If you are working with subflows, you need to rename node.parentNode to node.parentId. The parentNode attribute was a bit misleading, because it was not a reference to the parent node, but the id of the parent node.

旧 API

const nodes = [ // some nodes ... { id: 'xyz-id', position: { x: 0, y: 0 }, type: 'default', data: {}, parentNode: 'abc-id', }, ];

新 API

const nodes = [ // some nodes ... { id: 'xyz-id', position: { x: 0, y: 0 }, type: 'default', data: {}, parentId: 'abc-id', }, ];

7. 自定义节点属性

🌐 7. Custom node props

我们将 xPosyPos 属性重命名为 positionAbsoluteXpositionAbsoluteY

🌐 We renamed the xPos and yPos props to positionAbsoluteX and positionAbsoluteY

旧 API

function CustomNode({ xPos, yPos }) { ... }

新 API

function CustomNode({ positionAbsoluteX, positionAbsoluteY }) { ... }

8. 处理组件类名

🌐 8. Handle component class names

我们重命名了一些用于定义句柄当前状态的类。

🌐 We renamed some of the classes used to define the current state of a handle.

  • react-flow__handle-connecting 重命名为 connectingto / connectingfrom
  • react-flow__handle-valid 已重命名为 valid

9. getNodesBounds 选项

🌐 9. getNodesBounds options

第二个参数的类型已从 nodeOrigin 变更为 options.nodeOrigin

🌐 The type of the second param changed from nodeOrigin to options.nodeOrigin

旧 API

const bounds = getNodesBounds(nodes: Node[], nodeOrigin)

新 API

const bounds = getNodesBounds(nodes: Node[], { nodeOrigin })

10. 用于定义节点和边的 Typescript 更改

🌐 10. Typescript changes for defining nodes and edges

我们简化了类型,并修复了关于函数的问题,这些函数允许用户传递 NodeData 泛型。新的方式是用你所有节点的联合来定义你自己的节点类型。通过这个更改,你现在可以拥有多种不同数据结构的节点类型,并且始终能够通过检查 node.type 属性来区分它们。

🌐 We simplified types and fixed issues about functions where users could pass a NodeData generic. The new way is to define your own node type with a union of all your nodes. With this change, you can now have multiple node types with different data structures and always be able to distinguish by checking the node.type attribute.

新 API

type NumberNode = Node<{ value: number }, 'number'>; type TextNode = Node<{ text: string }, 'text'>; type AppNode = NumberNode | TextNode;

然后你可以像下面这样使用 AppNode 类型:

🌐 You can then use the AppNode type as the following:

const nodes: AppNode[] = [ { id: '1', type: 'number', data: { value: 1 }, position: { x: 100, y: 100 } }, { id: '2', type: 'text', data: { text: 'Hello' }, position: { x: 200, y: 200 } }, ];
const onNodesChange: onNodesChange<AppNode> = useCallback((changes) => setNodes(nds => applyChanges(changes, nds)), []);

你可以在Typescript 指南中阅读更多关于此内容的信息。

🌐 You can read more about this in the Typescript guide.

11. 重命名 nodeInternals

🌐 11. Rename nodeInternals

如果你正在使用 nodeInternals,你需要将其重命名为 nodeLookup

🌐 If you are using nodeInternals you need to rename it to nodeLookup.

旧 API

const node = useStore((s) => s.nodeInternals.get(id));

新 API

const node = useStore((s) => s.nodeLookup.get(id));

12. 移除已弃用的函数

🌐 12. Removal of deprecated functions

我们删除了以下弃用的函数:

🌐 We removed the following deprecated functions:

  • getTransformForBounds(被getViewportForBounds替换)
  • getRectOfNodes(被getNodesBounds替换)
  • project(被screenToFlowPosition替换)
  • getMarkerEndId
  • updateEdge(被reconnectEdge替换)

13. 自定义 applyNodeChangesapplyEdgeChanges

🌐 13. Custom applyNodeChanges and applyEdgeChanges

如果你自己编写了用于应用更改的函数,你需要处理新的“replace”事件。我们移除了“reset”事件,并添加了一个“replace”事件,用于替换特定的节点或边。

🌐 If you wrote your own function for applying changes, you need to handle the new “replace” event. We removed the “reset” event and added a “replace” event that replaces specific nodes or edges.

新功能

🌐 New features

既然你已经成功迁移到 v12,你可以使用所有的高级功能。如上所述,v12 的最大更新是:

🌐 Now that you successfully migrated to v12, you can use all the fancy features. As mentioned above, the biggest updates for v12 are:

1. 服务器端渲染

🌐 1. Server side rendering

你可以为节点定义 widthheighthandles。这使得可以在服务器上渲染流程并在客户端进行水合: 服务器端渲染指南

🌐 You can define width, height and handles for the nodes. This makes it possible to render a flow on the server and hydrate on the client: server side rendering guide.

  • 详情: 在 v11 中,widthheight 一旦节点被测量,库就会立即设置它们。现在这种情况仍然存在,但我们现在使用 measured.widthmeasured.height 来存储这些信息。在以前的版本中,总是对 widthheight 存在很多混淆。很难理解,你不能用它来传递实际的宽度或高度。此外,也不明显这些属性是由库添加的。我们认为新的实现解决了这两个问题:widthheight 是可选属性,可用于定义尺寸,而库设置的所有内容都存储在 measured 中。

2. 计算流

🌐 2. Computing flows

新的钩子 useHandleConnectionsuseNodesData 以及新的 updateNodeupdateNodeData 函数(两者都属于 useReactFlow)可以用来管理节点之间的数据流:计算流指南。我们还为边添加了这些辅助工具(updateEdgeupdateEdgeData)!

🌐 The new hooks useHandleConnections and useNodesData and the new updateNode and updateNodeData functions (both are part of useReactFlow) can be used to manage the data flow between your nodes: computing flows guide. We also added those helpers for edges (updateEdge and updateEdgeData)!

  • 细节: 在工作流中,一个节点的数据依赖于另一个节点是非常常见的。你更新节点A,并希望在连接的节点B上对这些更改做出反应。直到现在,每个人都必须想出一个自定义解决方案。通过这个版本,我们希望改变这一点,并为你提供高性能的辅助工具来处理类似的用例。

3. 黑夜间模式和 CSS 变量

🌐 3. Dark mode and CSS variables

React Flow 现在自带内置的暗黑模式,可以通过使用新的 colorMode 属性(“light”、“dark” 或 “system”)来切换: 暗黑模式示例

🌐 React Flow now comes with a built-in dark mode, that can be toggled by using the new colorMode prop (”light”, “dark” or “system”): dark mode example

  • 详情: 在这个版本中,我们希望让切换夜间模式和亮模式更容易,并为暗色流程提供更好的起点。如果你传入 colorMode="dark",我们会在封装器上添加类名“dark”,并用它来调整样式。为了让这个新功能的实现对我们这边更容易,我们将大部分样式切换到了 CSS 变量。这些变量也可以在用户端用于自定义流程。

4. 使用 TSDoc 提升开发者体验

🌐 4. A better DX with TSDoc

我们开始使用 TSDoc 以获得更好的开发体验(DX)。在开发过程中,你的 IDE 现在将显示组件属性和 Hooks 的文档。这对于我们来说是使库更易于访问和使用的一大步。我们也将在不久的将来使用 TSDoc 来生成文档。

🌐 We started to use TSDoc for a better DX. While developing your IDE will now show you the documentation for the props and hooks. This is a big step for us to make the library more accessible and easier to use. We will also use TSDoc in the near future to generate the documentation.

更多功能和更新

🌐 More features and updates

还有更多!除了新的主要功能,我们还添加了一些我们长期清单上的小功能:

🌐 There is more! Besides the new main features, we added some minor things that were on our list for a long time:

  • useConnection 钩子 使用此钩子,你可以访问正在进行的连接。例如,你可以使用它为句柄上色,或根据当前的起始/结束句柄为自定义连接线设置样式。
  • 受控 viewport 这是一个高级功能。可能的使用场景例如为视口添加动画,或对低分辨率屏幕进行变换取整。此功能带来了两个新属性: viewportonViewportChange
  • ViewportPortal 组件: 这使得可以在视口中渲染元素,而无需实现自定义节点。
  • onDelete 处理器:我们为 onDeleteNodesonDeleteEdges 添加了一个组合处理器,以便更容易地对删除操作做出反应。
  • onBeforeDelete 处理程序:使用此处理程序,你可以防止/管理删除。
  • isValidConnection 属性: 这使得为所有连接实现一个验证函数成为可能。它也会在以编程方式添加的边上被调用。
  • autoPanSpeed 属性: 用于在自动平移时控制速度。
  • paneClickDistance 属性: 鼠标按下/抬起之间触发点击的最大距离。
  • 背景组件:添加 patternClassName 属性,以便能够通过使用类名来设置背景图案的样式。如果你想使用 Tailwind 来设置背景图案样式,这将非常有用。
  • onMove 回调 会在库调用的视口更新(例如 fitView 或放大)时触发
  • deleteElements 现在返回已删除的节点和已删除的边
  • 为节点添加 origin 属性
  • 为边添加 selectable 属性
  • 节点调整器更新:调整组大小时子节点不会移动,范围和扩展被正确识别
  • BezierEdgeStepEdgeSmoothStepEdgeStraightEdge 组件的正确类型
  • 库创建的新边只有在设置了这些属性时才会有 sourceHandletargetHandle 属性。(我们以前会传 sourceHandle: nulltargetHandle: null
  • 当 z 索引更改时,边不会挂载/卸载
  • 连接线知道目标句柄的位置,以便路径正确绘制
  • nodeDragThreshold 默认是 1,而不是 0
  • 更好的选择框可用性(拖出流程时捕获)
  • selectabledeletabledraggableparentId 添加到 NodeProps
  • 当样式未加载时添加警告

内部更改

🌐 Internal changes

这些更改其实并不直接面向用户,但对于那些使用内部 React Flow 存储的人来说可能很重要:

🌐 These changes are not really user-facing, but it could be important for folks who are working with the internal React Flow store:

  • 最大的内部变化是我们创建了一个新的包 @xyflow/system,带有与框架无关的辅助工具,可以被 React Flow 和 Svelte Flow 使用
    • XYDrag 用于处理节点的拖动和选择
    • XYPanZoom 用于控制视口的平移和缩放
    • XYHandle 用于管理新连接
  • 我们将 nodeInternals 重命名为 nodeLookup。该映射用作查找,但我们在任何更改时都没有创建新的映射对象,因此它实际上仅用于查找。
  • 我们移除了内部的“重置”事件,并添加了一个“替换”事件,以便能够更新特定的节点。
  • 我们从商店中移除了 connectionNodeIdconnectionHandleIdconnectionHandleType,并添加了 connection.fromHandle.nodeIdconnection.fromHandle.id、…
  • data-id 添加到边
  • onNodeDragStartonNodeDragonNodeDragStop 也会在用户拖动选择时被调用(除了 onSelectionDragStartonSelectionDragonSelectionDragStop 之外)
Last updated on