React Flow keeps rendering edges connected to a hidden node (only edge.hidden is checked), unlike Svelte Flow after #5977
What platform were you using when you found the bug?
- React Flow / Svelte Flow version:
@xyflow/react12.11.6 - Browser and version: Chrome 128
- OS and version: any
Describe the Bug
An edge whose source or target node has hidden: true keeps rendering in React Flow. The only thing that suppresses an edge is edge.hidden; the hidden state of the nodes it connects is never consulted.
I traced it in current source:
packages/react/src/hooks/useVisibleEdgeIds.tsreturns every edge id whenonlyRenderVisibleElementsis off, and when it is on it filters withsourceNode && targetNode && isEdgeVisible(...). Neither branch checkssourceNode.hidden/targetNode.hidden.packages/react/src/components/EdgeWrapper/index.tsxbails out withreturn nullonly foredge.hiddenor a null position, and the position is null only when the node is missing fromnodeLookup(nullPosition). A hidden node is still innodeLookupwith its coordinates (adoptUserNodes/updateNodeInternalsinpackages/system/src/utils/store.tskeep the entry and only clearhandleBounds), sogetEdgePositionresolves and the edge draws to where the hidden node used to be.
Svelte Flow just changed this in the opposite direction. #5977 (merged, @xyflow/svelte) made getLayoutedEdges in packages/svelte/src/lib/store/visibleElements.ts skip an edge when sourceNode.hidden || targetNode.hidden, closing [SvelteFlow] #3387. That change did not reach the React package, so the two renderers now disagree on what node.hidden means for connected edges.
Steps to reproduce the bug or issue
- Render a React Flow with nodes
aandband an edgea -> b. - Update node
btohidden: true(leave the edge untouched, noedge.hidden). - Node
bdisappears, but thea -> bedge stays on the canvas as a stub pointing atb's last position.
Same setup in Svelte Flow after #5977: the edge is hidden together with the node.
Expected behavior
Either React Flow matches the Svelte Flow behavior from #5977 (a hidden source or target node also hides the edge), or, if the difference is intentional and users are expected to set edge.hidden themselves, the two packages should be documented as diverging on this point. Right now node.hidden silently means different things in the two renderers.
Additional context
Happy to open a PR adding the sourceNode.hidden || targetNode.hidden check to useVisibleEdgeIds (and an early return null in EdgeWrapper for the non-onlyRenderVisibleElements path) if you want the behaviors aligned.
Source: xyflow/xyflow