store.ts
Overview
The store.ts file implements a centralized state management store for managing graph data structures, specifically nodes and edges, within a React application. It leverages the Zustand state management library with middleware for devtools integration and immutable state updates via Immer.
This store is tailored for a flow editor or graph visualization UI that handles domain-specific nodes (RAGFlowNodeType) and edges (Edge) representing connections between nodes. It provides a rich set of actions and selectors for manipulating the graph state, including adding, updating, duplicating, and deleting nodes and edges, as well as managing selections and form data associated with nodes.
The store orchestrates complex workflows such as:
Maintaining consistency of edges and nodes.
Updating node forms when edges change.
Handling special semantics for different operator node types (e.g., Switch, Iteration, Agent).
Propagating changes downstream in agent-tool relationships.
It is designed to be consumed by React components to enable reactive and efficient graph editing experiences.
Detailed Documentation
Types
RFState (Type Alias)
Defines the shape of the graph store state and its actions.
Property / Method | Type / Signature | Description |
|---|---|---|
|
| Array of graph nodes. |
|
| Array of edges representing connections between nodes. |
|
| Array of currently selected node IDs. |
|
| Array of currently selected edge IDs. |
|
| ID of the node currently clicked/active. |
|
| ID of the currently selected tool. |
| Handler for node changes (add, update, remove). | |
| Handler for edge changes. | |
| [EdgeMouseHandler | undefined](/projects/311/73683) |
| [EdgeMouseHandler | undefined](/projects/311/73683) |
| Handler called when a new edge is created by connecting nodes. | |
| Handler called when selection of nodes/edges changes. | |
| Replace all nodes in the store. | |
| Replace all edges in the store. | |
| Replace edges downstream from a given node. | |
| [(nodeId: string, values: any, path?: (string | number)[]) => RAGFlowNodeType[]](/projects/311/73962) |
| Add a new node. | |
| [(id?: string | null) => RAGFlowNodeType |
| Update an existing node by replacing it. | |
| Add a new edge/connection. | |
| [(id: string) => Edge | undefined](/projects/311/71659) |
| Update node form data when a new edge connection is established. | |
| [(source: string, sourceHandle?: string | null, target?: string |
| Duplicate a node by ID with a new name. | |
| Specialized duplication for Iteration nodes including their children. | |
| Delete all currently selected edges. | |
| Delete an edge by its ID, including form updates to related nodes. | |
| Delete a node and its edges by ID. | |
| Delete an Agent node and all its downstream Agents and Tools recursively. | |
| Delete a Tool node linked to an Agent node by ID. | |
| Delete an Iteration node and all its child nodes and related edges. | |
| [(operatorName: Operator) => RAGFlowNodeType | undefined](/projects/311/73962) |
| Update a single mutable form field in a node. | |
| [(id?: string | null) => string |
| [(id?: string | null) => string |
| Update the display name of a node. | |
|
| Generate a unique node name given a base name by incrementing suffixes. |
| Set the clicked node ID in state. | |
| Set the clicked tool ID in state. | |
| [(id?: string | null) => RAGFlowNodeType |
| Delete edges from a source node and source handle (used for Switch conditions). | |
| [(id: string | null) => string |
| Update nodes' selection state based on an array of node IDs. |
The useGraphStore Hook
The core of this file is the useGraphStore hook created via zustand:
const useGraphStore = create<RFState>()(
devtools(
immer((set, get) => ({
// ...state and actions as described above
})),
{ name: 'graph', trace: true },
),
);
It uses
immermiddleware to allow easy immutable state updates with mutable syntax.It uses
devtoolsmiddleware for Redux DevTools integration, enabling time travel debugging and state inspection.The state contains nodes, edges, and UI selection / interaction state.
The store provides handlers for graph events (node/edge changes, connect, selection changes).
The store provides utility methods for complex graph manipulations, including duplication and deletion with domain-specific logic.
Key Functions and Methods
onNodesChange(changes: NodeChange[]): void
Applies node changes (add, update, remove) to the current nodes using the React Flow helper
applyNodeChanges.Updates state nodes accordingly.
onEdgesChange(changes: EdgeChange[]): void
Applies edge changes to current edges using
applyEdgeChanges.Updates state edges accordingly.
onConnect(connection: Connection): void
Adds a new edge based on a connection event.
Calls
updateFormDataOnConnectto update node forms based on new edges.
updateFormDataOnConnect(connection: Connection): void
Updates form data associated with a node when a new connection (edge) is created.
For example, for Switch operator nodes, updates their conditional form data to reflect the new connected target.
duplicateNode(id: string, name: string): void
Duplicates a node by ID with a new generated name.
Special handling for Iteration operator nodes, which duplicates children as well via
duplicateIterationNode.
deleteEdgeById(id: string): void
Deletes an edge by its ID.
Updates relevant node form data depending on the operator type of the source node (e.g., clears condition for Switch nodes).
deleteAgentDownstreamNodesById(id: string): void
Recursively deletes an Agent node and all downstream Agent and Tool nodes and edges.
Uses utility
deleteAllDownstreamAgentsAndToolto calculate all affected nodes and edges.
updateSwitchFormData(source: string, sourceHandle?: string | null, target?: string | null, isConnecting?: boolean): void
Updates Switch node form data to reflect connections/disconnections.
Handles multiple targets per source handle, updating "conditions" or "else" branches accordingly.
Implementation Details and Algorithms
State synchronization: Uses React Flow's helper functions (
applyNodeChanges,applyEdgeChanges) to keep graph state consistent with UI events.Form data updates: Node form data is deeply updated using utility
lodash.setto handle nested paths. This ensures that UI forms representing node configuration remain synchronized with graph structure.Edge filtering and comparison: Uses Lodash utilities (
differenceWith,intersectionWith) combined with a customisEdgeEqualcomparator to detect differences between edge sets when updating downstream edges.Node duplication: Generates new unique names for duplicated nodes, preserving relative positions and operator labels.
Graph traversal: Deletes downstream nodes and edges by recursively identifying all nodes reachable from a given Agent node, ensuring no orphaned nodes remain.
Selection management: Maintains arrays of selected node and edge IDs for UI highlighting and interaction.
Mouse event handling: On mouse enter/leave of edges, updates edge styles or states to reflect hover.
Interactions with Other Parts of the System
React Flow: The store depends on React Flow types and utilities (
Edge,Connection,addEdge,applyNodeChanges, etc.) and is designed to serve as the backing state for a React Flow graph interface.Node Types and Operators: The store uses domain-specific types and constants such as
RAGFlowNodeTypeandOperatorthat define node semantics and behavior. These are imported from the application’s internal modules.Utility Functions: The store imports multiple helper functions from
./utilsand./utils/delete-nodethat encapsulate logic for duplicating nodes, generating names, and deleting downstream nodes.UI Components: React components in the app consume this store hook (
useGraphStore) to read graph state and dispatch actions, enabling reactive UI updates.Redux DevTools: The devtools middleware integrates with Redux DevTools extension for debugging.
Usage Example
import useGraphStore from './store';
// In a React component
function GraphEditor() {
const nodes = useGraphStore((state) => state.nodes);
const edges = useGraphStore((state) => state.edges);
const addNode = useGraphStore((state) => state.addNode);
// Add new node on button click
const handleAddNode = () => {
const newNode = {
id: 'node-1',
data: { label: 'New Node', form: {} },
position: { x: 100, y: 200 },
type: 'default',
};
addNode(newNode);
};
return (
<>
<button onClick={handleAddNode}>Add Node</button>
{/* React Flow component here with nodes and edges */}
</>
);
}
Visual Diagram
classDiagram
class useGraphStore {
-nodes: RAGFlowNodeType[]
-edges: Edge[]
-selectedNodeIds: string[]
-selectedEdgeIds: string[]
-clickedNodeId: string
-clickedToolId: string
+onNodesChange(changes)
+onEdgesChange(changes)
+onConnect(connection)
+onEdgeMouseEnter(event, edge)
+onEdgeMouseLeave(event, edge)
+onSelectionChange(params)
+setNodes(nodes)
+setEdges(edges)
+setEdgesByNodeId(nodeId, edges)
+addNode(node)
+getNode(id)
+updateNode(node)
+addEdge(connection)
+getEdge(id)
+updateFormDataOnConnect(connection)
+updateSwitchFormData(source, sourceHandle, target, isConnecting)
+duplicateNode(id, name)
+duplicateIterationNode(id, name)
+deleteEdge()
+deleteEdgeById(id)
+deleteNodeById(id)
+deleteAgentDownstreamNodesById(id)
+deleteAgentToolNodeById(id)
+deleteIterationNodeById(id)
+findNodeByName(name)
+updateNodeForm(nodeId, values, path)
+updateMutableNodeFormItem(id, field, value)
+getOperatorTypeFromId(id)
+getParentIdById(id)
+updateNodeName(id, name)
+generateNodeName(name)
+setClickedNodeId(id)
+setClickedToolId(id)
+findUpstreamNodeById(id)
+deleteEdgesBySourceAndSourceHandle(source, sourceHandle)
+findAgentToolNodeById(id)
+selectNodeIds(nodeIds)
}
Summary
The store.ts file is a comprehensive state management module for a React Flow graph editor, managing nodes, edges, and associated UI state with domain-specific logic for node types and operator behavior. It provides a robust API for graph manipulation, ensuring state consistency and enabling advanced features like duplication, deletion, and form synchronization, all integrated with React Flow and Zustand's modern state management approach.