A production-ready Vite + React + TypeScript application demonstrating bidirectional transformation between a flat adjacency-list JSON format and React Flow's node/edge schema, with automatic Dagre tree layout and scalable logic separated via custom hooks.
@xyflow/reactv12 — the modern interactive flowchart librarydagre— automatic tree layout engineuuid— collision-free node ID generation- Vite + TypeScript + React 18
- Install dependencies:
npm install- Start the development server:
npm run dev- Open http://localhost:5173 in your browser.
FlowTree is designed to simplify viewing and editing hierarchical data models. It treats a flat JSON array of objects (with id and parentId) as the source of truth, converting it to interactive UI nodes.
- Custom Hook Logic (
useFlow): All React Flow state handlers, layout calculations, node modifications, and synchronizations are wrapped cleanly in a singleuseFlowhook. This keepsApp.tsxhighly readable and maintainable. - Dagre Auto-Layout: Instead of manually managing (x, y) coordinate constraints, node coordinates are inferred via Dagre on load, layout swap, and new node addition.
- Bidirectional Sync: Drag, drop, add, or delete nodes on the canvas, and the JSON sidebar automatically updates. Edit the JSON string in the sidebar, and the nodes redraw themselves.
Encapsulates all nodes and edges state and provides callable actions.
import { useFlow } from './hooks/useFlow';
function SequenceViewer() {
const { nodes, edges, onNodesChange, onEdgesChange, onConnect } = useFlow();
return (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
/>
);
}Converts your backend's flat adjacency list into React Flow nodes + edges, then runs Dagre to assign precise x/y coordinates for a perfect tree layout.
const { nodes, edges } = transformToFlow([
{ id: '1', name: 'Root', parentId: null },
{ id: '2', name: 'Child A', parentId: '1' },
{ id: '3', name: 'Child B', parentId: '1' },
]);Reconstructs the original flat format by inspecting edge targets to recover parentId relationships.
const treeData = transformToJSON(nodes, edges);
// → [{ id, name, parentId }, ...]Can be called any time to re-run Dagre. Supports 'TB' (top-down) and 'LR' (left-right).
| Feature | Description |
|---|---|
| Separation of Concerns | Application logic uses useFlow custom hook rather than polluting the component. |
| Auto-layout | Dagre positions nodes symmetrically on load and after adding nodes |
| Add nodes | Modal lets you pick a name and parent |
| Delete nodes | Select a node → press Delete |
| Connect nodes | Drag from a handle to another node to create an edge |
| Live JSON panel | Sidebar shows the serialized tree in real-time; supports editing and re-importing |
| Layout toggle | Switch between top-down and left-right tree orientations |
| Depth coloring | Nodes are color-coded by depth level |
src/
types.ts # TreeNode, FlowNodeData interfaces
utils/
transform.ts # transformToFlow, transformToJSON, applyDagreLayout
sampleData.ts # Initial demo tree
hooks/
useFlow.ts # Custom hook handling logic, nodes state, and handlers
components/
TreeNode.tsx # Custom RF node with depth-aware styling
JsonPanel.tsx # Live serialized JSON viewer/editor
AddNodeModal.tsx # Modal for adding nodes
App.tsx # Main layout and tree rendering view
main.tsx # Entry React root