跪拜 Guibai
← All articles
Frontend · React.js

15 Advanced React Flow Interactions, Recreated in an Open Workbench

By 来一首_We_go ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

These examples compress the trial-and-error part of building a canvas editor into readable, reusable reference code for React Flow applications. The layout and collaboration cases show where hidden state and coordinate conversions live, which matters as soon as a diagram feature moves beyond static nodes and edges.

Summary

Fifteen interaction examples from React Flow Pro now run together in one open workbench built on Next.js 16, React 19, TypeScript, and the official @xyflow/react package. It covers node position animation, flowchart shapes, WASM obstacle-avoidance routing, editable edges, alignment guides and snapping, copy/paste, undo/redo, grouping, expand/collapse, automatic layout, force-directed layout, dynamic tree layout, freehand drawing, and collaborative graph, form, cursor, and connection-draft synchronization.

Layout handling separates graph structure from geometry. Dynamic tree layout finds a parent through incoming edges, computes target positions with D3's stratify and tree, and uses a D3 timer to interpolate over roughly 300ms; rapid successive actions stop the old animation before it overwrites the new layout. Auto layout integrates Dagre, D3 Hierarchy, and ELK. Several surrounding steps are required: wait for node size measurement, convert Dagre's center coordinates to top-left positions, organize multiple trees under a virtual root, merge ELK's asynchronous results by node ID, and update edge endpoints when the layout direction changes. Force layout maps nodes to particles with repulsion, edge, and centering forces, and pins a particle with fx and fy while it is dragged.

Edge routing uses libavoid-js's WASM build, treating node rectangles as obstacles and Handles as directed pins, then writes computed bend points back into edge data. That write-back itself triggers another state update, a detail easy to miss. Collaboration uses Yjs + y-websocket and separates shared graph data (Y.Doc Maps), temporary online state (Awareness), and local view state (projection cache). A built-in backend creates the first node, clients wait for the first sync before showing the canvas, and Playwright regression tests cover browser isolation, form and graph sync, room isolation, initialization, and reconnection. Each example has its own Provider, graph state, and mutable cache, and the package exposes a unified entry point, so a Next.js app can lazy-load a single example through a dynamic import.

Takeaways
— Fifteen official React Flow Pro interaction examples are reproduced in one workbench on Next.js 16, React 19, TypeScript, and @xyflow/react.
— Dynamic tree layout inserts a node between A and B by replacing the edge with A to C and C to B, then transitions positions in about 300ms with a D3 timer.
— Auto layout integrates Dagre, D3 Hierarchy, and ELK; layout waits for node size measurement, converts center coordinates to top-left, uses a virtual root for multiple trees, and merges ELK's async results by node ID.
— Switching layout direction also updates edge entry and exit ports, not just the node coordinates.
— Obstacle-avoiding edges use libavoid-js WASM with node rectangles as obstacles and Handles as directed pins; moving a node updates obstacles and recomputes the path.
— Editable edges support straight, curved, and orthogonal path algorithms, plus control-point insertion/deletion and spacebar waypoint sampling while connecting.
— Collaborative editing uses Yjs + y-websocket; graph data lives in Y.Doc Maps, temporary cursors and connection drafts live in Awareness, and selection and measured sizes stay as local projection cache.
— Copy/paste collects only edges whose endpoints are both selected, remaps IDs, and offsets pasted nodes to preserve subgraph relationships.
— Grouping converts child positions to group-relative coordinates inside the group and back to canvas absolute coordinates on ungroup.
— Freehand drawing stores strokes as node-local point sets with pointer pressure and uses perfect-freehand to create outlines that remain selectable, movable, and scalable.
— Playwright regression tests cover independent browser sessions, form and graph sync, room isolation, first initialization, and reconnection.
— Run the workbench with Node 24.13.0 and pnpm 10.20.0; a Next.js Client Component can lazy-load single examples through next/dynamic.
Conclusions

Writing routing results back into edge data triggers another state update, so an auto-router that recomputes paths on every edge change risks feedback loops unless it tags or batches those writes.

Auto layout stays a pipeline even after a layout algorithm returns: node size measurement, coordinate conversion, asynchronous merging, and edge port updates have to be sequenced before the result matches the canvas.

Separating shared graph data, ephemeral awareness, and local view state makes collaborative editing manageable; the same split keeps each user's selection and measured sizes out of the shared document while cursors can disappear on disconnect.

The examples stay close to official React Flow Pro behavior, which makes them useful study material; production use still requires mapping them onto each product's data model and interaction rules.

Concepts & terms
Yjs Awareness
A channel inside Yjs for ephemeral presence data that is not part of the shared document. In this workbench it carries user identity, cursor positions, and in-progress connection drafts, and it is cleared when a client disconnects.
libavoid-js
A WASM-compiled version of the libavoid routing library. It treats node rectangles as obstacles and connection Handles as pins, then computes edge paths that avoid the obstacles.
perfect-freehand
A library that converts raw pointer coordinates and pressure into smooth stroke outlines, so freehand marks become selectable and transformable shapes instead of flat polylines.
ELK (Eclipse Layout Kernel)
A layout framework that computes graph arrangements; in the browser it runs asynchronously, and its results need to be matched back to node data by ID before being applied.
D3 stratify
A D3 helper that converts flat parent-child data into a tree hierarchy, used here to derive parent-child relationships from incoming edges before computing layout positions.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗