迁移到 React Flow 12
在您可以使用**React Flow 12 带来的新功能**,例如服务器端渲染、计算流程和暗黑模式之前,您需要首先解决以下重大更改。我们尽量将重大更改降至最低,但其中一些更改是实现新功能所必需的。
迁移指南
在开始迁移之前,您需要安装新的包。
npm install @xyflow/react
1. 新的 npm 包名称
包 reactflow
已重命名为 @xyflow/react
,并且不再是默认导入。您还需要调整样式导入。在 v12 之前,React Flow 分为多个包。现在不再是这种情况。如果您只使用了核心,您现在需要安装 @xyflow/react
包。
旧 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
属性用于测量的 width
和 height
所有测量的节点值现在都存储在 node.measured
中。除了新的包名称之外,这是最大的变化。在 React Flow 测量您的节点后,它会将尺寸写入 node.measured.width
和 node.measured.height
。如果您正在使用任何布局库,例如 dagre 或 elk,您现在需要从 node.measured
获取尺寸,而不是从 node
获取。如果您正在使用 width
和 height
,这些值现在将用作内联样式以指定节点尺寸。
旧 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.height
与 node.measured.width
/ node.measured.height
为了支持服务器端渲染,我们不得不稍微调整 API,以便用户可以更容易地传递节点尺寸。为此,我们更改了 node.width
和 node.height
属性的行为。在 React Flow 11 中,这些属性是测量值,仅用作参考。在 React Flow 12 中,这些属性用作内联样式以指定节点尺寸。如果您从数据库加载节点,您可能希望从节点中删除 width
和 height
属性,因为现在它们的行为略有不同。现在使用 width
和 height
意味着尺寸不是基于内容动态的,而是固定的。
旧 API
// in React Flow 11 you might 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,您可以在 服务器端渲染指南 中阅读相关内容。
4. 更新节点和边
我们不再支持使用对象变异更新节点和边。如果您想更新某个特定属性,您需要创建一个新的节点/边。
旧 API
setNodes((currentNodes) =>
currentNodes.map((node) => {
node.hidden = true;
return node;
}),
);
新 API
setNodes((currentNodes) =>
currentNodes.map((node) => ({
...node,
hidden: true,
})),
);
5. 将 onEdgeUpdate
(以及相关 API)重命名为 onReconnect
我们将 onEdgeUpdate
函数重命名为 onReconnect
,以及所有相关的 API(如下所示)。新名称更具描述性,并明确表明该函数用于重新连接边。
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
如果您正在使用子流程,您需要将 node.parentNode
重命名为 node.parentId
。 parentNode
属性有点误导,因为它不是对父节点的引用,而是父节点的 id
。
旧 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. 自定义节点属性
我们将 xPos
和 yPos
属性重命名为 positionAbsoluteX
和 positionAbsoluteY
旧 API
function CustomNode({ xPos, yPos }) {
...
}
新 API
function CustomNode({ positionAbsoluteX, positionAbsoluteY }) {
...
}
8. 处理组件类名
我们重命名了一些用于定义句柄当前状态的类。
react-flow__handle-connecting
重命名为connectingto
/connectingfrom
react-flow__handle-valid
重命名为valid
9. getNodesBounds
选项
第二个参数的类型已从 nodeOrigin
更改为 options.nodeOrigin
旧 API
const bounds = getNodesBounds(nodes: Node[], nodeOrigin)
新 API
const bounds = getNodesBounds(nodes: Node[], { nodeOrigin })
10. 用于定义节点和边的 TypeScript 更改
我们简化了类型并修复了关于函数的问题,其中用户可以传递 NodeData 泛型。新的方法是使用所有节点的并集定义自己的节点类型。通过这种更改,您现在可以拥有具有不同数据结构的多个节点类型,并且始终可以通过检查 node.type
属性来区分它们。
新 API
type NumberNode = Node<{ value: number }, 'number'>;
type TextNode = Node<{ text: string }, 'text'>;
type AppNode = NumberNode | TextNode;
然后,您可以像下面这样使用 AppNode
类型
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 指南 中阅读更多关于此内容的信息。
11. 重命名 nodeInternals
如果您正在使用 nodeInternals
,您需要将其重命名为 nodeLookup
。
旧 API
const node = useStore((s) => s.nodeInternals.get(id));
新 API
const node = useStore((s) => s.nodeLookup.get(id));
12. 删除弃用的函数
我们删除了以下弃用的函数:
getTransformForBounds
(已替换为getViewportForBounds
)getRectOfNodes
(已替换为getNodesBounds
)project
(已替换为screenToFlowPosition
)getMarkerEndId
updateEdge
(已替换为reconnectEdge
)
13. 自定义 applyNodeChanges
和 applyEdgeChanges
如果您自己编写了用于应用更改的函数,则需要处理新的“replace”事件。我们删除了“reset”事件并添加了“replace”事件,该事件替换特定节点或边。
新功能
现在您已成功迁移到 v12,您可以使用所有花哨的功能。如上所述,v12 的最大更新是
1. 服务器端渲染
您可以为节点定义 width
、height
和 handles
。这使得在服务器上渲染流程并在客户端进行水合成为可能:服务器端渲染指南。
- 详细信息:在 v11 中,
width
和height
在节点被测量后立即由库设置。这仍然发生,但我们现在使用measured.width
和measured.height
来存储这些信息。在以前的版本中,关于width
和height
始终存在很多困惑。很难理解,您不能使用它来传递实际的宽度或高度。也不清楚这些属性是由库添加的。我们认为新的实现解决了这两个问题:width
和height
是可选属性,可用于定义尺寸,库设置的所有内容都存储在measured
中。
2. 计算流程
新的钩子 useHandleConnections
和 useNodesData
以及新的 updateNode
和 updateNodeData
函数(两者都是 useReactFlow
的一部分)可用于管理节点之间的数据流:计算流程指南。我们还为边添加了这些助手(updateEdge
和 updateEdgeData
)!
- 详细信息:处理一个节点数据依赖于另一个节点的流程非常常见。您更新节点 A 并希望在连接的节点 B 中对这些更改做出反应。到目前为止,每个人都必须提出自定义解决方案。在本版本中,我们希望改变这种情况,并为您提供高性能的助手来处理此类用例。
3. 深色模式和 CSS 变量
React Flow 现在附带了一个内置的深色模式,可以通过使用新的 colorMode
属性(“light”、“dark”或“system”)切换:深色模式示例
- 详细信息:在本版本中,我们希望让在深色模式和浅色模式之间切换变得更容易,并为您提供更好的深色流程起点。如果您传递
colorMode="dark"
,我们将在包装器中添加类名“dark”并使用它来调整样式。为了使此新功能的实现对我们来说更容易,我们切换到 CSS 变量来实现大多数样式。这些变量也可以在用户端使用来定制流程。
4. 更好的 DX 与 TSDoc
我们开始使用 TSDoc 来获得更好的 DX。在开发过程中,您的 IDE 现在将向您显示属性和钩子的文档。这对我们来说是一个巨大的进步,让库更易于访问和使用。我们也将在不久的将来使用 TSDoc 来生成文档。
更多功能和更新
还有更多!除了新的主要功能外,我们还添加了一些我们列表中长期存在的小功能
useConnection
钩子:使用此钩子,您可以访问正在进行的连接。例如,您可以使用它对句柄进行着色,根据当前的起始/结束句柄来设置自定义连接线的样式。- 受控的
viewport
:这是一个高级功能。可能的用例是动画视窗或例如为较低分辨率的屏幕四舍五入变换。此功能带来了两个新属性:viewport
和onViewportChange
。 ViewportPortal
组件:这使得在视窗中渲染元素成为可能,而无需实现自定义节点。onDelete
处理程序:我们添加了一个组合的处理程序onDeleteNodes
和onDeleteEdges
以便更容易地对删除做出反应。onBeforeDelete
处理程序:使用此处理程序,您可以阻止/管理删除。isValidConnection
属性:这使得可以为所有连接实现一个验证函数。它也会针对以编程方式添加的边进行调用。autoPanSpeed
属性:用于控制自动平移时的速度。paneClickDistance
属性:鼠标按下/弹起之间触发点击的最大距离。- 背景组件:添加
patternClassName
属性以能够使用类名来设置背景图案的样式。如果您想使用 Tailwind 来设置背景图案的样式,这很有用。 onMove
回调会针对库调用的视窗更新(如 fitView 或 zoom-in)触发。deleteElements
现在返回删除的节点和删除的边。- 添加
origin
属性用于节点。 - 添加
selectable
属性用于边。 - 节点调整大小更新:当组大小调整时,子节点不会移动,范围和扩展被正确识别。
- 更正
BezierEdge
、StepEdge
、SmoothStepEdge
和StraightEdge
组件的类型。 - 由库创建的新边仅在设置这些属性时具有
sourceHandle
和targetHandle
属性。(我们以前传递sourceHandle: null
和targetHandle: null
) - 当边的 z 索引发生变化时,边不会挂载/卸载。
- 连接线了解目标句柄位置,以便正确绘制路径。
nodeDragThreshold
默认情况下为 1,而不是 0。- 更好的选择框可用性(在从流程中拖出时捕获)。
- 在
NodeProps
中添加selectable
、deletable
、draggable
和parentId
。 - 在样式未加载时添加警告。
内部更改
这些更改不是面向用户的,但对于那些使用 React Flow 内部存储的人来说可能很重要。
- 最大的内部更改是我们创建了一个新的包 @xyflow/system,它包含与框架无关的助手,React Flow 和 Svelte Flow 可以使用它们。
- XYDrag 用于处理节点和选择的拖动。
- XYPanZoom 用于控制视窗平移和缩放。
- XYHandle 用于管理新的连接。
- 我们重命名了
nodeInternals
为nodeLookup
。该映射用作查找,但我们不会在任何更改时创建新的映射对象,因此它实际上只用作查找。 - 我们删除了内部“reset”事件并添加了“replace”事件,以便能够更新特定节点。
- 我们从存储中删除了
connectionNodeId
、connectionHandleId
、connectionHandleType
并添加了connection.fromHandle.nodeId
、connection.fromHandle.id
等。 - 在边中添加
data-id
。 onNodeDragStart
、onNodeDrag
和onNodeDragStop
也会在用户拖动选择时被调用(除了onSelectionDragStart
、onSelectionDrag
、onSelectionDragStop
)。