diff --git a/.changeset/thirty-terms-grow.md b/.changeset/thirty-terms-grow.md new file mode 100644 index 00000000..a2f00e1f --- /dev/null +++ b/.changeset/thirty-terms-grow.md @@ -0,0 +1,5 @@ +--- +'@xyflow/react': patch +--- + +Fix `fitView` not working when returning early in `onNodesChange`. diff --git a/packages/react/src/components/BatchProvider/index.tsx b/packages/react/src/components/BatchProvider/index.tsx index 0ef7e399..382324da 100644 --- a/packages/react/src/components/BatchProvider/index.tsx +++ b/packages/react/src/components/BatchProvider/index.tsx @@ -28,7 +28,7 @@ export function BatchProvider(); const nodeQueueHandler = useCallback((queueItems: QueueItem[]) => { - const { nodes = [], setNodes, hasDefaultNodes, onNodesChange, nodeLookup } = store.getState(); + const { nodes = [], setNodes, hasDefaultNodes, onNodesChange, nodeLookup, fitViewQueued } = store.getState(); /* * This is essentially an `Array.reduce` in imperative clothing. Processing @@ -43,12 +43,22 @@ export function BatchProvider[] - ); + const changes = getElementsDiffChanges({ + items: next, + lookup: nodeLookup, + }) as NodeChange[]; + if (changes.length > 0) { + onNodesChange(changes); + } else if (fitViewQueued) { + // If there are no changes to the nodes, we still need to call setNodes + // to trigger a re-render and fitView. + window.requestAnimationFrame(() => { + const { fitViewQueued, nodes, setNodes } = store.getState(); + if (fitViewQueued) { + setNodes(nodes); + } + }); + } } }, []); const nodeQueue = useQueue(nodeQueueHandler);