Files
xyflow/src/hooks/useElementUpdater.ts
T

82 lines
2.5 KiB
TypeScript

import { useEffect } from 'react';
import isEqual from 'fast-deep-equal';
import { useStoreState, useStoreActions } from '../store/hooks';
import { parseElement, isNode, isEdge } from '../utils/graph';
import { Elements, Node, Edge } from '../types';
const useElementUpdater = (elements: Elements): void => {
const stateNodes = useStoreState((s) => s.nodes);
const stateEdges = useStoreState((s) => s.edges);
const setNodes = useStoreActions((a) => a.setNodes);
const setEdges = useStoreActions((a) => a.setEdges);
useEffect(() => {
const nodes: Node[] = elements.filter(isNode);
const edges: Edge[] = elements.filter(isEdge).map((e) => parseElement(e) as Edge);
const nextNodes: Node[] = nodes.map((propNode) => {
const existingNode = stateNodes.find((n) => n.id === propNode.id);
if (existingNode) {
const data = !isEqual(existingNode.data, propNode.data)
? { ...existingNode.data, ...propNode.data }
: existingNode.data;
const style = !isEqual(existingNode.style, propNode.style)
? { ...existingNode.style, ...propNode.style }
: existingNode.style;
const className = existingNode.className === propNode.className ? existingNode.className : propNode.className;
const isHidden = existingNode.isHidden === propNode.isHidden ? existingNode.isHidden : propNode.isHidden;
const positionChanged =
existingNode.position.x !== propNode.position.x || existingNode.position.y !== propNode.position.y;
const nodeProps = {
...existingNode,
data,
};
if (positionChanged) {
nodeProps.__rf = {
...existingNode.__rf,
position: propNode.position,
};
nodeProps.position = propNode.position;
}
if (typeof style !== 'undefined') {
nodeProps.style = style;
}
if (typeof className !== 'undefined') {
nodeProps.className = className;
}
if (typeof isHidden !== 'undefined') {
nodeProps.isHidden = isHidden;
}
return nodeProps;
}
return parseElement(propNode) as Node;
});
const nodesChanged: boolean = !isEqual(stateNodes, nextNodes);
const edgesChanged: boolean = !isEqual(stateEdges, edges);
if (nodesChanged) {
setNodes(nextNodes);
}
if (edgesChanged) {
setEdges(edges);
}
}, [elements, stateNodes, stateEdges]);
};
export default useElementUpdater;