refactor(general): fit view in store to prevent flickering, rename onLoad => onPaneReady
This commit is contained in:
@@ -36,6 +36,7 @@ interface StoreUpdaterProps {
|
||||
snapToGrid?: boolean;
|
||||
snapGrid?: SnapGrid;
|
||||
translateExtent?: CoordinateExtent;
|
||||
fitViewOnInit: boolean;
|
||||
}
|
||||
|
||||
const selector = (s: ReactFlowState) => ({
|
||||
@@ -58,6 +59,7 @@ const selector = (s: ReactFlowState) => ({
|
||||
setOnNodesChange: s.setOnNodesChange,
|
||||
setOnEdgesChange: s.setOnEdgesChange,
|
||||
reset: s.reset,
|
||||
setFitViewOnInit: s.setFitViewOnInit,
|
||||
});
|
||||
|
||||
const StoreUpdater = ({
|
||||
@@ -79,6 +81,7 @@ const StoreUpdater = ({
|
||||
snapGrid,
|
||||
snapToGrid,
|
||||
translateExtent,
|
||||
fitViewOnInit,
|
||||
}: StoreUpdaterProps) => {
|
||||
const {
|
||||
setNodes,
|
||||
@@ -100,6 +103,7 @@ const StoreUpdater = ({
|
||||
setOnEdgesChange,
|
||||
setConnectionMode,
|
||||
reset,
|
||||
setFitViewOnInit,
|
||||
} = useStore(selector, shallow);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -212,6 +216,10 @@ const StoreUpdater = ({
|
||||
}
|
||||
}, [onEdgesChange]);
|
||||
|
||||
useEffect(() => {
|
||||
setFitViewOnInit(fitViewOnInit);
|
||||
}, [fitViewOnInit]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
import React, { MutableRefObject, useEffect, useRef } from 'react';
|
||||
|
||||
import { Node } from '../../types';
|
||||
import { getRectOfNodes, getTransformForBounds } from '../../utils/graph';
|
||||
import { useStoreApi } from '../../store';
|
||||
import useZoomPanHelper from '../../hooks/useZoomPanHelper';
|
||||
|
||||
type ViewFitterInnerProps = {
|
||||
nodes: Node[];
|
||||
viewFitted: MutableRefObject<boolean>;
|
||||
};
|
||||
|
||||
function ViewFitterInner({ nodes, viewFitted }: ViewFitterInnerProps) {
|
||||
const store = useStoreApi();
|
||||
const { setTransform } = useZoomPanHelper();
|
||||
|
||||
useEffect(() => {
|
||||
if (nodes.length > 0 && !viewFitted.current) {
|
||||
const nodesInitialized = nodes.every((n) => n.width && n.height);
|
||||
|
||||
if (nodesInitialized) {
|
||||
const { width, height, minZoom, maxZoom } = store.getState();
|
||||
const bounds = getRectOfNodes(nodes);
|
||||
const [x, y, zoom] = getTransformForBounds(bounds, width, height, minZoom ?? 0.5, maxZoom ?? 2);
|
||||
|
||||
viewFitted.current = true;
|
||||
setTransform({ x, y, zoom });
|
||||
}
|
||||
}
|
||||
}, [nodes]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export type ViewFitterProps = {
|
||||
nodes: Node[];
|
||||
};
|
||||
|
||||
function ViewFitter({ nodes }: ViewFitterProps) {
|
||||
// we are storing the viewFitted in this wrapper to get rid of the useEffect of the inner component
|
||||
// that needs to check if the nodes changed after we fitted the view.
|
||||
const viewFitted = useRef<boolean>(false);
|
||||
|
||||
if (viewFitted.current) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <ViewFitterInner nodes={nodes} viewFitted={viewFitted} />;
|
||||
}
|
||||
|
||||
export default ViewFitter;
|
||||
Reference in New Issue
Block a user