React Flow Documentation

website·Indexed 39 days ago

https://reactflow.dev

A library for building node-based editors and diagrams. Documentation covers quick start guides, API references for the ReactFlowProvider and core ReactFlow components, accessibility standards (WCAG 2.1 AA), and implementation of custom UI components using shadcn/ui, Tailwind CSS, and Animated SVG Edges.

Tokens
95.2K
Snippets
395
Records
446
Agent score
74%

What's inside React Flow

  1. Overview of Web Audio API for interactive node editors

    The Web Audio API allows for the creation of an audio-processing graph (signal chain) where various audio nodes are connected. Key components include:

    • AudioContext: The central controller used to create nodes and manage the audio processing state (suspend/resume).
    • Source Nodes: Generate audio (e.g., OscillatorNode, MediaElementAudioSourceNode).
    • Effect Nodes: Modify audio (e.g., GainNode for volume, DelayNode, ConvolverNode).
    • Output Nodes: The final destination for audio (e.g., AudioDestinationNode).

    Audio processing occurs on a separate native thread, ensuring that sound generation continues even if the main UI thread is blocked.

  2. Manage React Flow state using Zustand

    To maintain a clean component architecture, use a state management library like Zustand to handle nodes, edges, and their changes. This allows the ReactFlow component to remain declarative while the store handles the logic for updating positions, connections, and custom data.
    import { create } from 'zustand';
    import { addEdge, applyNodeChanges, applyEdgeChanges } from '@xyflow/react';
    
    const useStore = create((set, get) => ({
      nodes: initialNodes,
      edges: initialEdges,
      onNodesChange: (changes) => {
        set({
          nodes: applyNodeChanges(changes, get().nodes),
        });
      },
      onEdgesChange: (changes) => {
        set({
          edges: applyEdgeChanges(changes, get().edges),
        });
      },
      onConnect: (connection) => {
        set({
          edges: addEdge(connection, get().edges),
        });
      },
    }));
  3. Configure and customize the MiniMap component

    The <MiniMap /> component provides an overview of the flow.

    • Interactivity: Set pannable or zoomable props to true to allow users to interact with the viewport via the minimap.
    • Custom Nodes: Use the nodeComponent prop to provide a custom SVG component for nodes.
    • Dynamic Styling: The nodeColor, nodeStrokeColor, and nodeClassName props can be functions that take a Node object to determine the style based on node properties (e.g., node type).
    import { ReactFlow, MiniMap } from '@xyflow/react';
    
    // Example: Interactive MiniMap with dynamic coloring
    function nodeColor(node) {
      switch (node.type) {
        case 'input': return '#6ede87';
        case 'output': return '#6865A5';
        default: return '#ff0072';
      }
    }
    
    export default function Flow() {
      return (
        <ReactFlow nodes={[...]} edges={[...]}>
          <MiniMap 
            pannable 
            zoomable 
            nodeColor={nodeColor} 
            nodeComponent={(props) => <circle cx={props.x} cy={props.y} r="50" />} 
          />
        </ReactFlow>
      );
    }
  4. Render complex HTML labels with EdgeLabelRenderer

    Because edges are SVG-based, rendering complex HTML labels directly inside them is limited. The <EdgeLabelRenderer /> component acts as a portal that renders its children in a <div> positioned on top of the edges, allowing for standard HTML/CSS layout and styling for labels.
  5. Use D3-Force for physics-based node layout

    For non-tree graphs or more dynamic positioning, use d3-force. Unlike d3-hierarchy, d3-force is a physics-based layouting library that applies forces to nodes. Because the algorithm is iterative, it requires a mechanism to compute the layout across multiple renders. It is more complex to configure than dagre or d3-hierarchy but offers more flexibility for complex graph structures.
  6. Use D3-Hierarchy for tree-based layouts in React Flow

    D3-Hierarchy is recommended when a graph is known to be a tree with a single root node. It provides advanced layouting algorithms including simple trees, tree maps, partition layouts, and enclosure diagrams.
  7. Customize nodes, handles, and edges in React Flow

    React Flow provides a flexible system for extending the visual and functional aspects of the graph:

    • Custom Nodes: You can create custom components to embed interactive forms, dynamic visualizations, or multiple handles. Register them via the nodeTypes prop.
    • Handles: These are the attachment points for edges. They are standard div elements that can be styled and positioned anywhere within a custom node.
    • Edges: Edges connect a source node to a target node. Built-in types include default (bezier), smoothstep, step, and straight. Custom edges allow for custom routing, removal buttons, and complex SVG styling.
  8. Programmatically focus a node using fitView

    The fitView function from useReactFlow can be used to center the viewport on specific nodes. To focus on a node, you only need to provide an array of objects containing the node's id. You do not need to pass the full node object.
    import { useReactFlow } from '@xyflow/react';
    
    function MyComponent() {
      const { fitView } = useReactFlow();
    
      const handleMoveToNode = (id: string) => {
        fitView({
          nodes: [{ id }],
          duration: 150,
        });
      };
    
      return <button onClick={() => handleMoveToNode('node-1')}>Go to Node 1</button>;
    }
  9. Meet WCAG 2.1 AA standards with React Flow

    React Flow provides several built-in features to help developers satisfy WCAG 2.1 AA criteria:

    • Keyboard Operability: Supports Tab navigation, Enter/Space interaction, and arrow key movement for nodes.
    • Screen Reader Support: Uses semantic ARIA roles (e.g., role="group") and supports aria-label and aria-roledescription for nodes and edges.
    • ARIA Live Regions: Includes an aria-live="assertive" region via the A11yDescriptions component to notify users of dynamic updates like node movements.
    • Focus Management: Automatically ensures nodes scroll into view when focused and provides contextual keyboard instructions.
  10. Test React Flow applications with Cypress or Playwright

    React Flow relies on rendering DOM elements to measure nodes for edge rendering. Because Cypress and Playwright run in a real browser environment, no additional setup or mocking is required to test React Flow applications.
  11. Create a basic React Flow component

    To render a flow, use the <ReactFlow /> component. The parent container must have a defined width and height (e.g., 100% or 100vh) because React Flow relies on these dimensions to calculate the viewport. You can nest <Background /> and <Controls /> inside <ReactFlow /> to add a dotted grid and viewport controls.
    import { ReactFlow, Background, Controls } from '@xyflow/react';
    import '@xyflow/react/dist/style.css';
    
    export default function App() {
      return (
        <div style={{ height: '100%', width: '100%' }}>
          <ReactFlow colorMode="system">
            <Background />
            <Controls />
          </ReactFlow>
        </div>
      );
    }
  12. Handle dynamic child node creation on connection drop

    To create a child node when a connection is dropped on the pane (rather than an existing node), use the onConnectEnd callback. By checking if the event target is the .react-flow__pane and utilizing screenToFlowPosition from useReactFlow, you can calculate the exact coordinates relative to the parent node to place the new child node.
    const onConnectEnd: OnConnectEnd = useCallback((event) => {
      const targetIsPane = (event.target as Element).classList.contains('react-flow__pane');
      if (targetIsPane && connectingNodeId.current) {
        const parentNode = nodeLookup.get(connectingNodeId.current);
        const childNodePosition = getChildNodePosition(event, parentNode);
        if (parentNode && childNodePosition) {
          addChildNode(parentNode, childNodePosition);
        }
      }
    }, [getChildNodePosition]);