refactor(general): fit view in store to prevent flickering, rename onLoad => onPaneReady

This commit is contained in:
moklick
2021-12-09 07:24:45 +01:00
parent 3a52efbb1f
commit 88582a86cc
17 changed files with 96 additions and 100 deletions
+8
View File
@@ -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;
};
-51
View File
@@ -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;