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. ノードの測定された widthheight を示す measured 属性

測定されたすべてのノード値は、node.measured に格納されるようになりました。新しいパッケージ名に加えて、これは最大の変更点です。React Flowはノードを測定した後、寸法を node.measured.widthnode.measured.height に書き込みます。dagreやelkなどのレイアウトライブラリを使用している場合は、node の代わりに node.measured から寸法を取得する必要があります。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.width 属性と node.height 属性の動作を変更しました。React Flow 11では、これらの属性は測定値であり、参照としてのみ使用されていました。React Flow 12では、これらの属性はインラインスタイルとして使用され、ノードの寸法を指定します。データベースからノードを読み込む場合は、動作が少し変更されたため、ノードから width 属性と height 属性を削除することをお勧めします。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(下記参照)の名前を変更しました。新しい名前はより記述的で、関数がエッジの再接続に使用されることを明確にしています。

  • updateEdgereconnectEdge に名前変更されました
  • onEdgeUpdateStartonReconnectStart に名前変更されました
  • onEdgeUpdateonReconnect に名前変更されました
  • onEdgeUpdateEndonReconnectEnd に名前変更されました
  • edgeUpdaterRadiusreconnectRadius に名前変更されました
  • edge.updatableedge.reconnectable に名前変更されました
  • edgesUpdatableedgesReconnectable に名前変更されました

古いAPI

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

新しいAPI

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

6. parentNodeの名前を parentId に変更

サブフローを使用している場合は、node.parentNodenode.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 プロパティの名前を positionAbsoluteXpositionAbsoluteY に変更しました

古いAPI

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

新しいAPI

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

8. コンポーネントクラス名の処理

ハンドルの現在の状態を定義するために使用されるクラスの一部を名前変更しました。

  • react-flow__handle-connectingconnectingto / connectingfrom に名前変更されました
  • react-flow__handle-validvalid に名前変更されました

9. getNodesBounds オプション

2番目のパラメータのタイプが 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. 非推奨関数の削除

以下の非推奨関数を削除しました。

  • getTransformForBoundsgetViewportForBounds に置き換えられました)
  • getRectOfNodesgetNodesBounds に置き換えられました)
  • projectscreenToFlowPosition に置き換えられました)
  • getMarkerEndId
  • updateEdgereconnectEdge に置き換えられました)

13. カスタム applyNodeChangesapplyEdgeChanges

変更を適用するための独自の関数を作成した場合、新しい「replace」イベントを処理する必要があります。「reset」イベントは削除され、特定のノードまたはエッジを置き換える「replace」イベントが追加されました。

新機能

v12 に正常に移行したので、すべての素晴らしい機能を使用できます。上記のように、v12 の最大の更新点は次のとおりです。

1. サーバーサイドレンダリング

ノードの widthheighthandles を定義できます。これにより、サーバー上でフローをレンダリングし、クライアント上でハイドレートすることができます:サーバーサイドレンダリングガイド

  • **詳細:** v11 では、ノードが測定されるとすぐにライブラリによって widthheight が設定されていました。これは引き続き行われますが、この情報を格納するために measured.widthmeasured.height を使用するようになりました。以前のバージョンでは、widthheight について常に多くの混乱がありました。実際の幅や高さを渡すために使用できないことを理解するのは困難です。また、これらの属性がライブラリによって追加されることは明らかではありません。新しい実装は両方の問題を解決すると考えています。widthheight は、寸法を定義するために使用できるオプションの属性であり、ライブラリによって設定されるすべてのものは measured に格納されます。

2. フローの計算

新しいフック useHandleConnectionsuseNodesData、および新しい updateNodeupdateNodeData 関数(どちらも useReactFlow の一部)を使用して、ノード間のデータフローを管理できます:フローの計算ガイド。エッジ用のヘルパー(updateEdgeupdateEdgeData)も追加しました!

  • **詳細:** あるノードのデータが別のノードに依存するフローを扱うことは非常に一般的です。ノードAを更新し、接続されたノードBでこれらの変更に反応したいとします。これまで、誰もがカスタムソリューションを考え出す必要がありました。このバージョンでは、これを変更し、このようなユースケースを処理するための高性能なヘルパーを提供します。

3. ダークモードとCSS変数

React Flow には、新しい colorMode プロパティ(「light」、「dark」、または「system」)を使用して切り替えることができる、組み込みのダークモードが付属するようになりました:ダークモードの例

  • **詳細:** このバージョンでは、ダークモードとライトモードの切り替えを容易にし、ダークフローのより良い出発点を提供します。colorMode="dark" を渡すと、ラッパークラス名「dark」が追加され、スタイリングの調整に使用されます。この新機能の実装を容易にするために、ほとんどのスタイルで CSS 変数に切り替えました。これらの変数は、ユーザーランドでもフローをカスタマイズするために使用できます。

4. TSDoc によるより良い DX

より良い DX のために TSDoc を使用し始めました。開発中に、IDE にプロパティとフックのドキュメントが表示されるようになりました。これは、ライブラリをよりアクセスしやすく、使いやすくするための大きな一歩です。近い将来、TSDoc を使用してドキュメントを生成する予定です。

その他の機能と更新

他にもあります!新しい主な機能に加えて、長い間リストに載っていたマイナーな事項をいくつか追加しました。

  • **useConnection フック:** このフックを使用すると、進行中の接続にアクセスできます。たとえば、現在の開始/終了ハンドルに基づいて、ハンドルを色付けしたり、カスタム接続線をスタイルしたりするために使用できます。
  • **制御された viewport:** これは高度な機能です。考えられるユースケースは、ビューポートをアニメーション化したり、たとえば低解像度画面の変換を丸めたりすることです。この機能は、2つの新しいプロパティをもたらします:viewportonViewportChange
  • **ViewportPortal コンポーネント:** これにより、カスタムノードを実装する必要なく、ビューポートに要素をレンダリングできます。
  • **onDelete ハンドラ**:削除に反応しやすくするために、 onDeleteNodesonDeleteEdges のための結合ハンドラを追加しました。
  • **onBeforeDelete ハンドラ**:このハンドラを使用すると、削除を防止/管理できます。
  • **isValidConnection プロパティ:** すべての接続に1つの検証関数を実装することができます。プログラムで追加されたエッジにも呼び出されます。
  • **autoPanSpeed プロパティ:** 自動パン中の速度を制御します。
  • **paneClickDistance プロパティ:** クリックをトリガーするmousedown/up間の最大距離。
  • **背景コンポーネント**:クラス名を使用して背景パターンをスタイルできるように、 patternClassName プロパティを追加します。これは、たとえばTailwindで背景パターンをスタイルする場合に便利です。
  • **onMove コールバック**は、ライブラリによって呼び出されたビューポートの更新(fitViewやズームインなど)に対してトリガーされます
  • **deleteElements** は、削除されたノードと削除されたエッジを返すようになりました
  • ノードに **origin 属性**を追加
  • エッジに **selectable 属性**を追加
  • **ノードリサイザーの更新**:グループのサイズ変更時に子ノードが移動せず、エクステントと展開が正しく認識される
  • BezierEdgeStepEdgeSmoothStepEdgeStraightEdgeコンポーネントの正しい型
  • ライブラリによって新しく作成されたエッジは、これらの属性が設定されている場合にのみ、 sourceHandletargetHandle 属性を持ちます。(以前は sourceHandle: nulltargetHandle: null を渡していました)
  • z-indexが変更されてもエッジはマウント/アンマウントされない
  • 接続線はターゲットハンドルの位置を認識しているため、パスが正しく描画される
  • nodeDragThreshold は0ではなくデフォルトで1
  • 選択ボックスの使い勝手の向上(フローからドラッグアウト中のキャプチャ)
  • NodePropsselectabledeletabledraggableparentId を追加
  • スタイルがロードされていない場合の警告を追加

内部変更

これらの変更は実際にはユーザー向けではありませんが、内部のReact Flowストアで作業している人にとっては重要かもしれません

  • 最大の内部変更は、React FlowとSvelte Flowで使用できる **フレームワークに依存しないヘルパーを備えた新しいパッケージ@xyflow/system** を作成したことです。
    • ノードと選択のドラッグを処理するための **XYDrag**
    • ビューポートのパンとズームを制御するための **XYPanZoom**
    • 新しい接続を管理するための **XYHandle**
  • nodeInternalsnodeLookup に名前変更しました。このマップはルックアップとして機能しますが、変更のたびに新しいマップオブジェクトを作成することはないため、実際にはルックアップとしてのみ役立ちます。
  • 内部「reset」イベントを削除し、特定のノードを更新できるように「replace」イベントを追加しました。
  • ストアから connectionNodeIdconnectionHandleIdconnectionHandleType を削除し、 connection.fromHandle.nodeIdconnection.fromHandle.id、… を追加しました
  • エッジに data-id を追加する
  • ユーザーが選択範囲をドラッグしたときにも、onNodeDragStartonNodeDragonNodeDragStop が呼び出されます(onSelectionDragStartonSelectionDragonSelectionDragStop に加えて)。