diff --git a/.changeset/bright-brooms-glow.md b/.changeset/bright-brooms-glow.md new file mode 100644 index 00000000..8f29eb3b --- /dev/null +++ b/.changeset/bright-brooms-glow.md @@ -0,0 +1,5 @@ +--- +'@xyflow/react': patch +--- + +fix(fitView): only trigger for resize observer diff --git a/packages/react/src/hooks/useUpdateNodeInternals.ts b/packages/react/src/hooks/useUpdateNodeInternals.ts index 63965d72..6486afd8 100644 --- a/packages/react/src/hooks/useUpdateNodeInternals.ts +++ b/packages/react/src/hooks/useUpdateNodeInternals.ts @@ -25,6 +25,6 @@ export function useUpdateNodeInternals(): UpdateNodeInternals { } }); - requestAnimationFrame(() => updateNodeInternals(updates)); + requestAnimationFrame(() => updateNodeInternals(updates, { triggerFitView: false })); }, []); } diff --git a/packages/react/src/store/index.ts b/packages/react/src/store/index.ts index 01604143..c45d8f2d 100644 --- a/packages/react/src/store/index.ts +++ b/packages/react/src/store/index.ts @@ -77,7 +77,7 @@ const createStore = ({ // Every node gets registerd at a ResizeObserver. Whenever a node // changes its dimensions, this function is called to measure the // new dimensions and update the nodes. - updateNodeInternals: (updates) => { + updateNodeInternals: (updates, params = { triggerFitView: true }) => { const { triggerNodeChanges, nodeLookup, @@ -105,23 +105,28 @@ const createStore = ({ updateAbsolutePositions(nodeLookup, parentLookup, { nodeOrigin }); - // we call fitView once initially after all dimensions are set - let nextFitViewDone = fitViewDone; + if (params.triggerFitView) { + // we call fitView once initially after all dimensions are set + let nextFitViewDone = fitViewDone; - if (!fitViewDone && fitViewOnInit) { - nextFitViewDone = fitViewSync({ - ...fitViewOnInitOptions, - nodes: fitViewOnInitOptions?.nodes, - }); + if (!fitViewDone && fitViewOnInit) { + nextFitViewDone = fitViewSync({ + ...fitViewOnInitOptions, + nodes: fitViewOnInitOptions?.nodes, + }); + } + + // here we are cirmumventing the onNodesChange handler + // in order to be able to display nodes even if the user + // has not provided an onNodesChange handler. + // Nodes are only rendered if they have a width and height + // attribute which they get from this handler. + set({ fitViewDone: nextFitViewDone }); + } else { + // we always want to trigger useStore calls whenever updateNodeInternals is called + set({}); } - // here we are cirmumventing the onNodesChange handler - // in order to be able to display nodes even if the user - // has not provided an onNodesChange handler. - // Nodes are only rendered if they have a width and height - // attribute which they get from this handler. - set({ fitViewDone: nextFitViewDone }); - if (changes?.length > 0) { if (debug) { console.log('React Flow: trigger node changes', changes); diff --git a/packages/react/src/types/store.ts b/packages/react/src/types/store.ts index 8ddd2ff8..beeb85b3 100644 --- a/packages/react/src/types/store.ts +++ b/packages/react/src/types/store.ts @@ -152,7 +152,7 @@ export type ReactFlowActions = { setNodes: (nodes: NodeType[]) => void; setEdges: (edges: EdgeType[]) => void; setDefaultNodesAndEdges: (nodes?: NodeType[], edges?: EdgeType[]) => void; - updateNodeInternals: (updates: Map) => void; + updateNodeInternals: (updates: Map, params?: { triggerFitView: boolean }) => void; updateNodePositions: UpdateNodePositions; resetSelectedElements: () => void; unselectNodesAndEdges: (params?: UnselectNodesAndEdgesParams) => void;