Dagre Tree
This example shows how you can integrate dagre.js with React Flow to create simple tree layouts. A good alternative to dagre is elkjs if you are looking for a more advanced layouting library.
import React, { useCallback } from 'react'; import ReactFlow, { addEdge, ConnectionLineType, useNodesState, useEdgesState } from 'react-flow-renderer'; import dagre from 'dagre'; import { initialNodes, initialEdges } from './nodes-edges.js'; import './index.css'; const dagreGraph = new dagre.graphlib.Graph(); dagreGraph.setDefaultEdgeLabel(() => ({})); const nodeWidth = 172; const nodeHeight = 36; const getLayoutedElements = (nodes, edges, direction = 'TB') => { const isHorizontal = direction === 'LR'; dagreGraph.setGraph({ rankdir: direction }); nodes.forEach((node) => { dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight }); }); edges.forEach((edge) => { dagreGraph.setEdge(edge.source, edge.target); }); dagre.layout(dagreGraph); nodes.forEach((node) => { const nodeWithPosition = dagreGraph.node(node.id); node.targetPosition = isHorizontal ? 'left' : 'top'; node.sourcePosition = isHorizontal ? 'right' : 'bottom'; // We are shifting the dagre node position (anchor=center center) to the top left // so it matches the React Flow node anchor point (top left). node.position = { x: nodeWithPosition.x - nodeWidth / 2, y: nodeWithPosition.y - nodeHeight / 2, }; return node; }); return { nodes, edges }; }; const { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements( initialNodes, initialEdges ); const LayoutFlow = () => { const [nodes, setNodes, onNodesChange] = useNodesState(layoutedNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(layoutedEdges); const onConnect = useCallback( (params) => setEdges((eds) => addEdge({ ...params, type: ConnectionLineType.SmoothStep, animated: true }, eds)), [] ); const onLayout = useCallback( (direction) => { const { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements( nodes, edges, direction ); setNodes([...layoutedNodes]); setEdges([...layoutedEdges]); }, [nodes, edges] ); return ( <div className="layoutflow"> <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} onConnect={onConnect} connectionLineType={ConnectionLineType.SmoothStep} fitView /> <div className="controls"> <button onClick={() => onLayout('TB')}>vertical layout</button> <button onClick={() => onLayout('LR')}>horizontal layout</button> </div> </div> ); }; export default LayoutFlow;