學習疑難排解

遷移至 React Flow 12

您可以在此處找到舊版 React Flow 的文件:v11v10v9

在您可以使用 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 屬性,用於測量的 widthheight

所有測量的節點值現在都儲存在 node.measured 中。除了新的套件名稱之外,這是最大的變更。在 React Flow 測量您的節點之後,它會將尺寸寫入 node.measured.widthnode.measured.height。如果您使用任何佈局函式庫(如 dagre 或 elk),您現在需要從 node.measured 而不是 node 取得尺寸。如果您使用 widthheight,這些值現在將用作內嵌樣式以指定節點尺寸。

舊版 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 vs node.measured.width / node.measured.height

為了支援伺服器端渲染,我們必須稍微重組 API,以便使用者可以更輕鬆地傳遞節點尺寸。為此,我們變更了 node.widthnode.height 屬性的行為。在 React Flow 11 中,這些屬性是測量值,僅用作參考。在 React Flow 12 中,這些屬性用作內嵌樣式以指定節點尺寸。如果您從資料庫載入節點,您可能想要從節點中移除 widthheight 屬性,因為現在的行為略有不同。現在使用 widthheight 表示尺寸不是根據內容動態調整,而是固定的。

舊版 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.parentIdparentNode 屬性有點誤導,因為它不是對父節點的參考,而是父節點的 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. 自訂節點屬性

我們將 xPosyPos 屬性重新命名為 positionAbsoluteXpositionAbsoluteY

舊版 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. 自訂 applyNodeChangesapplyEdgeChanges

如果您撰寫了自己的函式來套用變更,您需要處理新的「replace」事件。我們移除了「reset」事件,並新增了「replace」事件,以取代特定的節點或邊緣。

新功能

現在您已成功移轉至 v12,您可以使用所有炫酷的功能。如上所述,v12 的最大更新是

1. 伺服器端渲染

您可以為節點定義 widthheighthandles。這使得在伺服器上渲染流程並在客戶端上注水成為可能:伺服器端渲染指南

  • 詳細資訊:在 v11 中,widthheight 會在節點測量後立即由程式庫設定。這種情況仍然會發生,但我們現在使用 measured.widthmeasured.height 來儲存此資訊。在之前的版本中,對於 widthheight 總是存在很多混淆。很難理解您不能使用它來傳遞實際的寬度或高度。而且這些屬性由程式庫新增也不是很明顯。我們認為新的實作解決了這兩個問題:widthheight 是可選屬性,可用於定義尺寸,而程式庫設定的所有內容都會儲存在 measured 中。

2. 計算流程

新的 Hook useHandleConnectionsuseNodesData 以及新的 updateNodeupdateNodeData 函式(兩者都是 useReactFlow 的一部分)可用於管理節點之間的資料流程:計算流程指南。我們也為邊緣新增了這些輔助程式 (updateEdgeupdateEdgeData)!

  • 詳細資訊:處理一個節點資料依賴於另一個節點的流程非常常見。您更新節點 A,並希望在連接的節點 B 中對這些變更做出反應。到目前為止,每個人都必須提出自訂的解決方案。透過此版本,我們想要改變這種情況,並為您提供高效的輔助程式來處理此類用例。

3. 深色模式和 CSS 變數

React Flow 現在具有內建的深色模式,可以使用新的 colorMode 屬性(”light”、“dark” 或 “system”)進行切換:深色模式範例

  • 詳細資訊:透過此版本,我們希望讓您更輕鬆地在深色和淺色模式之間切換,並為您提供更好的深色流程起點。如果您傳遞 colorMode="dark",我們會將類別名稱「dark」新增至包裝器,並使用它來調整樣式。為了使此新功能的實作對我們來說更容易,我們將大多數樣式切換為 CSS 變數。這些變數也可以在使用者端使用,來自訂流程。

4. 透過 TSDoc 改善 DX

我們開始使用 TSDoc 來改善 DX。在開發時,您的 IDE 現在會顯示屬性和 Hook 的文件。這是我們讓程式庫更容易存取和使用的重要一步。我們也將在不久的將來使用 TSDoc 來產生文件。

更多功能和更新

還有更多!除了新的主要功能之外,我們還新增了一些長期以來在我們清單上的小東西

  • useConnection Hook透過此 Hook,您可以存取正在進行的連線。例如,您可以使用它來為控制碼著色,並根據目前的開始/結束控制碼設計自訂連線線條的樣式。
  • 受控 viewport這是一項進階功能。可能的用例是為視口製作動畫或為較低解析度的螢幕四捨五入轉換。此功能帶來了兩個新屬性:viewportonViewportChange
  • ViewportPortal 元件:這使得可以在視口中渲染元素,而無需實作自訂節點。
  • onDelete 處理常式:我們新增了 onDeleteNodesonDeleteEdges 的組合處理常式,使其更容易對刪除做出反應。
  • onBeforeDelete 處理常式:使用此處理常式,您可以防止/管理刪除。
  • isValidConnection 屬性:這使得可以為所有連線實作一個驗證函式。它也會針對以程式設計方式新增的邊緣呼叫。
  • autoPanSpeed 屬性:用於控制自動平移時的速度。
  • paneClickDistance 屬性:mousedown/up 之間的最大距離,會觸發點擊。
  • 背景元件:新增 patternClassName 屬性,以便能夠使用類別名稱設定背景圖案的樣式。如果您想要使用 Tailwind 設定背景圖案的樣式,這會很有用。
  • onMove 回呼會針對程式庫叫用的視口更新 (例如 fitView 或 zoom-in) 觸發
  • deleteElements 現在會傳回已刪除的節點和已刪除的邊緣
  • 為節點新增 origin 屬性
  • 為邊緣新增 selectable 屬性
  • 節點調整大小器更新:調整群組大小時,子節點不會移動,會正確辨識範圍和展開
  • 修正 BezierEdgeStepEdgeSmoothStepEdgeStraightEdge 元件的類型
  • 程式庫建立的新邊緣只有在設定這些屬性時,才會具有 sourceHandletargetHandle 屬性。(我們過去會傳遞 sourceHandle: nulltargetHandle: null)
  • 邊緣不會在其 z-index 變更時掛載/卸載
  • 連線線條知道目標控制碼的位置,以便正確繪製路徑
  • nodeDragThreshold 預設為 1,而不是 0
  • 更好的選取方塊可用性(在流程外拖曳時擷取)
  • selectabledeletabledraggableparentId 新增至 NodeProps
  • 在未載入樣式時新增警告

內部變更

這些變更並非真正面向使用者,但對於使用內部 React Flow 儲存區的人來說可能很重要

  • 最大的內部變更是我們建立了一個新的套件 @xyflow/system,其中包含框架不可知的輔助程式,可供 React Flow 和 Svelte Flow 使用
    • XYDrag 用於處理拖曳節點和選取
    • XYPanZoom 用於控制視口的平移和縮放
    • XYHandle 用於管理新的連線
  • 我們將 nodeInternals 重新命名為 nodeLookup。該對應表可作為查閱,但我們不會在任何變更時建立新的對應物件,因此它實際上僅作為查閱有用。
  • 我們移除了內部的「reset」事件,並新增了一個「replace」事件,以便能夠更新特定的節點。
  • 我們從儲存區中移除了 connectionNodeIdconnectionHandleIdconnectionHandleType,並新增了 connection.fromHandle.nodeIdconnection.fromHandle.id、…
  • 為邊緣新增 data-id
  • 當使用者拖曳選取範圍時,也會呼叫 onNodeDragStartonNodeDragonNodeDragStop (除了 onSelectionDragStartonSelectionDragonSelectionDragStop)