react-flow-implementation

安装量: 135
排名: #6407

安装

npx skills add https://github.com/existential-birds/beagle --skill react-flow-implementation

React Flow Implementation Quick Start import { ReactFlow, useNodesState, useEdgesState, addEdge } from '@xyflow/react'; import '@xyflow/react/dist/style.css';

const initialNodes = [ { id: '1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } }, { id: '2', position: { x: 200, y: 100 }, data: { label: 'Node 2' } }, ];

const initialEdges = [{ id: 'e1-2', source: '1', target: '2' }];

export default function Flow() { const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);

const onConnect = useCallback( (connection) => setEdges((eds) => addEdge(connection, eds)), [setEdges] );

return (

); }

Core Patterns TypeScript Types import type { Node, Edge, NodeProps, BuiltInNode } from '@xyflow/react';

// Define custom node type with data shape type CustomNode = Node<{ value: number; label: string }, 'custom'>;

// Combine with built-in nodes type MyNode = CustomNode | BuiltInNode; type MyEdge = Edge<{ weight?: number }>;

// Use throughout app const [nodes, setNodes] = useNodesState(initialNodes);

Custom Nodes import { memo } from 'react'; import { Handle, Position, type NodeProps } from '@xyflow/react';

// Define node type type CounterNode = Node<{ count: number }, 'counter'>;

// Always wrap in memo for performance const CounterNode = memo(function CounterNode({ data, isConnectable }: NodeProps) { return ( <>

Count: {data.count} {/ nodrag prevents dragging when interacting with button /}
</> ); });

// Register in nodeTypes (define OUTSIDE component to avoid re-renders) const nodeTypes = { counter: CounterNode };

// Use in ReactFlow

Multiple Handles // Use handle IDs when a node has multiple handles of same type

// Connect with specific handles const edge = { id: 'e1-2', source: '1', sourceHandle: 'a', target: '2', targetHandle: null };

Custom Edges import { BaseEdge, EdgeProps, getSmoothStepPath } from '@xyflow/react';

function CustomEdge({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data }: EdgeProps) { const [edgePath, labelX, labelY] = getSmoothStepPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, });

return ( <> {data?.label} </> ); }

const edgeTypes = { custom: CustomEdge };

State Management Controlled (Recommended for Production) // External state with change handlers const [nodes, setNodes] = useState(initialNodes); const [edges, setEdges] = useState(initialEdges);

const onNodesChange = useCallback( (changes) => setNodes((nds) => applyNodeChanges(changes, nds)), [] );

const onEdgesChange = useCallback( (changes) => setEdges((eds) => applyEdgeChanges(changes, eds)), [] );

Using useReactFlow import { useReactFlow, ReactFlowProvider } from '@xyflow/react';

function FlowControls() { const { getNodes, setNodes, addNodes, updateNodeData, getEdges, setEdges, addEdges, fitView, zoomIn, zoomOut, setViewport, deleteElements, toObject, } = useReactFlow();

const addNode = () => { addNodes({ id: ${Date.now()}, position: { x: 100, y: 100 }, data: { label: 'New' } }); };

return ; }

// Must wrap in provider when using useReactFlow function App() { return ( ); }

Updating Node Data const { updateNodeData } = useReactFlow();

// Merge with existing data updateNodeData(nodeId, { label: 'Updated' });

// Replace data entirely updateNodeData(nodeId, { newField: 'value' }, { replace: true });

Viewport & Fit View // Fit on initial render

// Programmatic control const { fitView, setViewport, getViewport, zoomTo } = useReactFlow();

// Fit to specific nodes fitView({ nodes: [{ id: '1' }, { id: '2' }], duration: 500 });

// Set exact viewport setViewport({ x: 100, y: 100, zoom: 1.5 }, { duration: 300 });

Connection Validation const isValidConnection = useCallback((connection: Connection) => { // Prevent self-connections if (connection.source === connection.target) return false;

// Custom validation logic const sourceNode = getNode(connection.source); const targetNode = getNode(connection.target);

return sourceNode?.type !== targetNode?.type; }, []);

Common Props Reference <ReactFlow // Core data nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange}

// Custom types (define OUTSIDE component) nodeTypes={nodeTypes} edgeTypes={edgeTypes}

// Connections onConnect={onConnect} connectionMode={ConnectionMode.Loose} // Allow target-to-target isValidConnection={isValidConnection}

// Viewport fitView minZoom={0.1} maxZoom={4} defaultViewport={{ x: 0, y: 0, zoom: 1 }}

// Interaction nodesDraggable={true} nodesConnectable={true} elementsSelectable={true} panOnDrag={true} zoomOnScroll={true}

// Additional components

CSS Classes for Interaction Class Effect nodrag Prevent dragging when clicking element nowheel Prevent zoom on wheel events nopan Prevent panning from element nokey Prevent keyboard events (use on inputs) Additional Components

See ADDITIONAL_COMPONENTS.md for MiniMap, Controls, Background, NodeToolbar, NodeResizer.

返回排行榜