React Flow auto layout with dagre for custom, variable-size nodes
Variable-size nodes break dagre's centering, first paint flickers, and straight chains render with kinked edges. Here is the why and the fix for each. Every React Flow and dagre tutorial shows the same thing: uniform gray boxes, laid out in a neat tree, everything centered. You copy the pattern, wire it up, and it works. Then you replace the gray boxes with real cards. A title that wraps to two…
Variable-size nodes pose three challenges to React Flow's auto layout using dagre: misaligned centering, initial flicker during rendering, and kinked edges in straight chains. Dagre centers a parent node on the average of its children's center positions, which results in uneven spacing when the child nodes vary in size. To fix this, a post-processing step recomputes the parent's cross-axis position as the midpoint of the children's bounding box.
React Flow can only measure a node after it renders, but the layout engine requires the sizes beforehand. The solution is to seed nodes with visibility: hidden, measure sizes before layout, and then apply positions. This prevents the common flicker effect of nodes jumping into place. Straight edges in React Flow often bend due to different handles' heights for nodes of varying sizes.
For linear chains, align the child's center to the source node's center; for branching nodes, anchor the elbow to the shared hub, ensuring consistent alignment despite varying node sizes. Additionally, dagre's crossing-minimization algorithm reshuffles the order of fan-out branches, disrupting the declaration order. To preserve the original order, the library maintains the declared edge order and accepts the extra crossings that may occur.
The extracted library, react-flow-auto-layout, provides a streamlined solution with a single hook, useAutoLayout, handling measurement and layout. It also offers a pure layout function and specific edge customization for aligned step connectors. While the library addresses the three main challenges, it is best suited for smaller graphs, as the measurement pass incurs a hidden render.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.