xyflow: fitView() on onLoad doesn't seem to act, but works with Control Panel
Hello there,
I am currently working on the fitView() method on my diagram, but I see that it doesn’t seem to fit on onLoad().
I am doing this, following the doc :
const onLoad = (reactFlowInstance) => {
reactFlowInstance.fitView();
}
But it doesn’t happen. But when I click on the fitView button on the control, it does work !
Here is how I use the props in the component :
<ReactFlow
elements={elements}
elementsSelectable={diagramMode !== "View"}
onLoad={onLoad}
nodesDraggable={nodesDraggableState}
paneMoveable
zoomOnScroll
arrowHeadColor="#206584"
nodesConnectable={nodesConnectableState}
defaultPosition={[0, 0]}
defaultZoom={1}
onNodeDragStop={onNodeDragStop}
onConnect={onConnect}
onElementClick={openForm}
onElementsRemove={onElementsRemove}
deleteKeyCode={46}
>
<MiniMap
nodeColor={(node) => {
switch (node.type) {
case "input":
return "red";
case "default":
return "#00ff00";
case "output":
return "rgb(0,0,255)";
default:
return "#eee";
}
}}
/>
<Controls />
</ReactFlow>
I tried adding padding as a parameter, to do as the Control Panel . Here is the code of the control panel I found in the sources :
{showFitView && (
<div
className="react-flow__controls-button react-flow__controls-fitview"
onClick={() => fitView({ padding: 0.1 })}
>
<FitviewIcon />
</div>
)}
But even when adding padding like this, it does not change the behaviour. I tried to look at the older issues but couln’t find something related.
Would you have any idea about the source of this ?
Thank you, Yoann
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 5
- Comments: 15 (3 by maintainers)
Commits related to this issue
- fix(fitView): don't let defaultPosition overwrite fitView on load #533 — committed to xyflow/xyflow by moklick 4 years ago
- fix(fitView): don't let defaultPosition overwrite fitView on load #533 — committed to xyflow/xyflow by moklick 4 years ago
This seems to happen when the elements are changed after ReactFlow gets mounted (e.g. with
useEffect
like in the custom node example). That is because the onLoad handler gets called before the new elements are passed to the component. You can workaround this by waiting for the elements to change in an extrauseEffect
hook. Minimal example: https://codesandbox.io/s/unruffled-ishizaka-fhljt?file=/src/App.jshappening to me too. Fixed it by adding setTimeout, i.e.
EDIT: this might be caused by setting ‘defaultPosition’, it doesn’t happen once I comment it out
For anyone stumbling across this because
fitView
doesn’t seem to be working, the answer in my case was to wait foruseNodesInitialized
[1] to returntrue
after changing the nodes.Simply calling
setNodes(...)
thenreactFlowInstance.fitView()
doesn’t act on the nodes you just set. It can be a few react update cycles before the nodes you set are fully settled inside RF, so waiting on oneuseEffect
isn’t good enough. EvensetTimeout
didn’t work unless the timeout was at least about 100ms for me. But auseEffect(()=>{ ... fitView ... }, nodesInitialized)
worked a charm.(Also for anyone wondering about
onLoad
in OP – it’s now calledonInit
.)[1] https://reactflow.dev/docs/api/hooks/use-nodes-initialized/
yes , after layout then
setNodes
then callreactFlowInstance.fitView()
does not work. setTimeout work for me. but that’s not a good solution. it introduce fickers since the view change suddenly in one frame.@moklick can you give a fitView utility funtion that accept newNodes as parameter (not nodes snapshot) , let us do the layout and fit view in one render and avoid the flickers.
Fixed it by adding
onInit
anduseEffect
. Those steps are:As my case was caused by
elements
being ready when the component was first rendered I worked around it in the end by just not trying to render the ReactFlow component until i had some elements to draw and then it worked fine. E.g. adapting the example from above, i just:just wanted to add that this happens to me too in version
6.2.2
and in order to fix it I userequestAnimationFrame
instead ofsetTimeout
but i has the same effect. In my case I’m not changing the defaultPosition. And even if I do set a defaultPosition, it doesn’t do anything when using it withfitView