学ぶ高度な使用法

ステート管理ライブラリの使用

このガイドでは、React Flowのコアコンセプトと、カスタムノードの実装方法について、既にご存知であることを前提としています。また、ステート管理ライブラリの概念と、その使用方法についても理解している必要があります。

このガイドでは、ステート管理ライブラリZustandをReact Flowと組み合わせて使用する方法について説明します。すべてのノードに、背景色を更新するカラーチューザーがある小さなアプリを作成します。このガイドでは、React Flow内部で既にZustandを使用しているため、Zustandを使用していますが、もちろん、ReduxRecoilJotaiなどの他のライブラリも使用できます。

以前のガイドや例で見たように、React Flowは、ダイアグラムのノードとエッジを処理するために、ローカルコンポーネントの状態を簡単に使用できます。アプリが大きくなり、たとえばノード内から状態を変更したい場合、より複雑になる可能性があります。ノードデータフィールドを通じて関数を渡すことを避けるために、Reactコンテキストを使用するか、このガイドで説明するようにステート管理ライブラリを追加できます。

Zustandのインストール

上記のように、この例ではZustandを使用します。ZustandはReduxに少し似ています。状態を変更するためのアクションと、状態にアクセスするためのフックを備えた中央ストアがあります。Zustandは以下を使用してインストールできます。

npm install --save zustand

ストアの作成

Zustandを使用すると、ストアの値と関数にアクセスするためのフックを作成できます。グラフの基本的なインタラクティビティを実現するために、nodesedges、およびonNodesChangeonEdgesChangeonConnectsetNodessetEdges関数をストアに格納します。

export default function App() {
  const data: string = "world"

  return <h1>Hello {data}</h1>
}

読み取り専用

これが基本的な設定です。React Flowによってトリガーされた変更(ノードまたはエッジのドラッグ、選択、削除)を処理できるノードとエッジを備えたストアができました。App.tsxファイルを見ると、きれいに保たれていることがわかります。すべてのデータとアクションはストアの一部となり、useStoreフックでアクセスできるようになりました。

色変更アクションの実装

特定のノードのdata.colorフィールドを更新するために、新しいupdateNodeColorアクションを追加します。これを行うために、ノードIDと新しい色をアクションに渡し、ノードを反復処理して、一致するノードを新しい色で更新します。

updateNodeColor: (nodeId: string, color: string) => {
  set({
    nodes: get().nodes.map((node) => {
      if (node.id === nodeId) {
        // it's important to create a new object here, to inform React Flow about the changes
        return { ...node, data: { ...node.data, color } };
      }
 
      return node;
    }),
  });
};

この新しいアクションは、次のようにReactコンポーネントで使用できます。

const updateNodeColor = useStore((s) => s.updateNodeColor);
...
<button onClick={() => updateNodeColor(nodeId, color)} />;

カラーチューザーノードの追加

このステップでは、ColorChooserNodeコンポーネントを実装し、ユーザーが色を変更したときにupdateNodeColorを呼び出します。カラーチューザーのカスタム部分は、カラー入力です。

<input
  type="color"
  defaultValue={data.color}
  onChange={(evt) => updateNodeColor(id, evt.target.value)}
  className="nodrag"
/>

ユーザーが色を変更するときに誤ってノードをドラッグしないように、nodragクラス名を追加し、onChangeイベントハンドラーでupdateNodeColorを呼び出します。

export default function App() {
  const data: string = "world"

  return <h1>Hello {data}</h1>
}

読み取り専用

カラーチューザーをクリックして、ノードの背景を変更できるようになりました。