学习高级使用

使用状态管理库

在本指南中,我们假设您已经了解 React Flow 的 核心概念 以及如何实现 自定义节点。您还应该熟悉状态管理库的概念以及如何使用它们。

在本指南中,我们解释了如何将 React Flow 与状态管理库 Zustand 一起使用。我们将构建一个小型应用程序,其中每个节点都有一个颜色选择器,用于更新其背景颜色。在本指南中,我们使用 Zustand,因为我们在 React Flow 内部已经使用了它,但当然,您也可以使用其他库,例如 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 挂钩访问。

实现颜色更改操作

我们添加一个新的 updateNodeColor 操作来更新特定节点的 data.color 字段。为此,我们将节点 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>
}

只读

您现在可以单击颜色选择器并更改节点的背景。