跳到主要内容

使用状态管理库

备注

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

在本指南中,我们将解释如何将 React Flow 与状态管理库 Zustand"使用LCEL"结合使用。我们将构建一个小应用程序,其中每个节点都有一个可以更新其背景颜色的颜色选择器。在本指南中,我们使用 Zustand,因为我们已经在 React Flow 内部使用它,但当然您可以使用任何其他库,如 Redux"使用LCEL"、Recoil"使用LCEL"或 Jotai(也会在新选项卡中打开)。

正如您可能在之前的指南和示例中看到的那样,React Flow 可以轻松地与本地组件状态一起使用来处理图表的节点和边缘。例如,当您的应用程序增长并且您想要从节点内更改状态时,事情可能会变得更加复杂。为了避免通过节点数据字段传递函数,您可以使用 React 上下文"使用LCEL"或添加状态管理库,如本指南中所述。

安装 Zustand

如上所述,我们在此示例中使用 Zustand。 Zustand 有点像 Redux:您有一个中央存储,其中包含更改状态的操作和访问状态的钩子。您可以通过以下方式安装 Zustand:

npm install --save zustand

创建存储

Zustand 允许您创建一个钩子来访问商店的值和功能。我们将节点和边以及 onNodesChange、onEdgesChange、onConnect、setNodes 和 setEdges 函数放入存储中以获得图形的基本交互性:

参考预览:https://codesandbox.io/p/sandbox/magical-architecture-h85zfk?file=%2Fstore.ts&utm_medium=sandpack

这是基本设置。我们现在有一个包含节点和边的存储,可以处理由 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。

参考预览:https://codesandbox.io/p/sandbox/wizardly-hill-x48rv4?file=%2FColorChooserNode.tsx&utm_medium=sandpack

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