react-flow-architecture

React Flow Architecture

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react-flow-architecture" with this command: npx skills add existential-birds/beagle/existential-birds-beagle-react-flow-architecture

React Flow Architecture

When to Use React Flow

Good Fit

  • Visual programming interfaces

  • Workflow builders and automation tools

  • Diagram editors (flowcharts, org charts)

  • Data pipeline visualization

  • Mind mapping tools

  • Node-based audio/video editors

  • Decision tree builders

  • State machine designers

Consider Alternatives

  • Simple static diagrams (use SVG or canvas directly)

  • Heavy real-time collaboration (may need custom sync layer)

  • 3D visualizations (use Three.js, react-three-fiber)

  • Graph analysis with 10k+ nodes (use WebGL-based solutions like Sigma.js)

Architecture Patterns

Package Structure (xyflow)

@xyflow/system (vanilla TypeScript) ├── Core algorithms (edge paths, bounds, viewport) ├── xypanzoom (d3-based pan/zoom) ├── xydrag, xyhandle, xyminimap, xyresizer └── Shared types

@xyflow/react (depends on @xyflow/system) ├── React components and hooks ├── Zustand store for state management └── Framework-specific integrations

@xyflow/svelte (depends on @xyflow/system) └── Svelte components and stores

Implication: Core logic is framework-agnostic. When contributing or debugging, check if issue is in @xyflow/system or framework-specific package.

State Management Approaches

  1. Local State (Simple Apps)

// useNodesState/useEdgesState for prototyping const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);

Pros: Simple, minimal boilerplate Cons: State isolated to component tree

  1. External Store (Production)

// Zustand store example import { create } from 'zustand';

interface FlowStore { nodes: Node[]; edges: Edge[]; setNodes: (nodes: Node[]) => void; onNodesChange: OnNodesChange; }

const useFlowStore = create<FlowStore>((set, get) => ({ nodes: initialNodes, edges: initialEdges, setNodes: (nodes) => set({ nodes }), onNodesChange: (changes) => { set({ nodes: applyNodeChanges(changes, get().nodes) }); }, }));

// In component function Flow() { const { nodes, edges, onNodesChange } = useFlowStore(); return <ReactFlow nodes={nodes} onNodesChange={onNodesChange} />; }

Pros: State accessible anywhere, easier persistence/sync Cons: More setup, need careful selector optimization

  1. Redux/Other State Libraries

// Connect via selectors const nodes = useSelector(selectNodes); const dispatch = useDispatch();

const onNodesChange = useCallback((changes: NodeChange[]) => { dispatch(nodesChanged(changes)); }, [dispatch]);

Data Flow Architecture

User Input → Change Event → Reducer/Handler → State Update → Re-render ↓ [Drag node] → onNodesChange → applyNodeChanges → setNodes → ReactFlow ↓ [Connect] → onConnect → addEdge → setEdges → ReactFlow ↓ [Delete] → onNodesDelete → deleteElements → setNodes/setEdges → ReactFlow

Sub-Flow Pattern (Nested Nodes)

// Parent node containing child nodes const nodes = [ { id: 'group-1', type: 'group', position: { x: 0, y: 0 }, style: { width: 300, height: 200 }, }, { id: 'child-1', parentId: 'group-1', // Key: parent reference extent: 'parent', // Key: constrain to parent position: { x: 10, y: 30 }, // Relative to parent data: { label: 'Child' }, }, ];

Considerations:

  • Use extent: 'parent' to constrain dragging

  • Use expandParent: true to auto-expand parent

  • Parent z-index affects child rendering order

Viewport Persistence

// Save viewport state const { toObject, setViewport } = useReactFlow();

const handleSave = () => { const flow = toObject(); // flow.nodes, flow.edges, flow.viewport localStorage.setItem('flow', JSON.stringify(flow)); };

const handleRestore = () => { const flow = JSON.parse(localStorage.getItem('flow')); setNodes(flow.nodes); setEdges(flow.edges); setViewport(flow.viewport); };

Integration Patterns

With Backend/API

// Load from API useEffect(() => { fetch('/api/flow') .then(r => r.json()) .then(({ nodes, edges }) => { setNodes(nodes); setEdges(edges); }); }, []);

// Debounced auto-save const debouncedSave = useMemo( () => debounce((nodes, edges) => { fetch('/api/flow', { method: 'POST', body: JSON.stringify({ nodes, edges }), }); }, 1000), [] );

useEffect(() => { debouncedSave(nodes, edges); }, [nodes, edges]);

With Layout Algorithms

import dagre from 'dagre';

function getLayoutedElements(nodes: Node[], edges: Edge[]) { const g = new dagre.graphlib.Graph(); g.setGraph({ rankdir: 'TB' }); g.setDefaultEdgeLabel(() => ({}));

nodes.forEach((node) => { g.setNode(node.id, { width: 150, height: 50 }); });

edges.forEach((edge) => { g.setEdge(edge.source, edge.target); });

dagre.layout(g);

return { nodes: nodes.map((node) => { const pos = g.node(node.id); return { ...node, position: { x: pos.x, y: pos.y } }; }), edges, }; }

Performance Scaling

Node Count Guidelines

Nodes Strategy

< 100 Default settings

100-500 Enable onlyRenderVisibleElements

500-1000 Simplify custom nodes, reduce DOM elements

1000 Consider virtualization, WebGL alternatives

Optimization Techniques

<ReactFlow // Only render nodes/edges in viewport onlyRenderVisibleElements={true}

// Reduce node border radius (improves intersect calculations) nodeExtent={[[-1000, -1000], [1000, 1000]]}

// Disable features not needed elementsSelectable={false} panOnDrag={false} zoomOnScroll={false} />

Trade-offs

Controlled vs Uncontrolled

Controlled Uncontrolled

More boilerplate Less code

Full state control Internal state

Easy persistence Need toObject()

Better for complex apps Good for prototypes

Connection Modes

Strict (default) Loose

Source → Target only Any handle → any handle

Predictable behavior More flexible

Use for data flows Use for diagrams

<ReactFlow connectionMode={ConnectionMode.Loose} />

Edge Rendering

Default edges Custom edges

Fast rendering More control

Limited styling Any SVG/HTML

Simple use cases Complex labels

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

tailwind-v4

No summary provided by upstream source.

Repository SourceNeeds Review
General

react-flow

No summary provided by upstream source.

Repository SourceNeeds Review
General

react-router-v7

No summary provided by upstream source.

Repository SourceNeeds Review
General

vitest-testing

No summary provided by upstream source.

Repository SourceNeeds Review