状态管理详解
React Flow 用 Zustand(常 createWithEqualityFn + Object.is)持有 nodes、edges、viewport、选择集、连接态等。用户 props 与 store 通过 StoreUpdater 等同步。
1. 为何选 Zustand
| 点 | 说明 |
|---|---|
| 体积小 | 图编辑器自带状态多,不想再背 Redux 样板 |
| 细粒度订阅 | NodeRenderer 只订 nodes 相关切片 |
组件外可 getState | 拖拽/键盘回调里读写在 store API |
| Provider | 多画布实例需隔离 store |
与通用 Zustand 实践一致:Zustand 性能。
2. Store 里大致有什么
| 状态域 | 用途 |
|---|---|
nodes / edges | 图数据 |
viewport | 平移缩放 |
nodeLookup / 索引 | 快速按 id 查节点(实现随版本演进) |
connection* | 拖拽连线中的 from/to 状态 |
selection | 选中节点/边 |
transform | 与 DOM 同步的矩阵 |
Actions:setNodes、onNodesChange 包装、updateNode、updateEdge、setViewport、fitView 等。
3. 受控 vs 非受控
| 模式 | 行为 |
|---|---|
| 非受控 | 改 setNodes 等 action,内部更新 store |
| 受控 | 父组件持 nodes/edges,onNodesChange 里 applyNodeChanges 后回传 props,StoreUpdater 写入 store |
变更描述用 NodeChange / EdgeChange 数组(移动、选中、删除…),由 system 包 applyNodeChanges 归约。
4. 性能相关
- Renderer 用 selector + shallow 避免整 store 刷新。
- 批量拖拽时合并 change,减少 React 渲染次数(见 05-性能优化)。
- 大列表讨论过 Map vs 数组(Issue #3892),以实现为准。
5. 总结
状态层 = Zustand + 变更归约;业务仍应 useCallback 稳定 handlers、受控时保持 immutable 更新。实现入口:packages/react/src/store/。