refactor(reducer): only iterate incoming elements once

This commit is contained in:
moklick
2021-02-14 14:52:39 +01:00
parent acd6b76b14
commit 5aa78cf2fc
+50 -57
View File
@@ -18,72 +18,66 @@ import { ReactFlowAction } from './actions';
import { initialState } from './index'; import { initialState } from './index';
type ElementsSplitted = { type NextElements = {
nodeElements: Node[]; nextNodes: Node[];
edgeElements: Edge[]; nextEdges: Edge[];
}; };
export default function reactFlowReducer(state = initialState, action: ReactFlowAction): ReactFlowState { export default function reactFlowReducer(state = initialState, action: ReactFlowAction): ReactFlowState {
switch (action.type) { switch (action.type) {
case constants.SET_ELEMENTS: { case constants.SET_ELEMENTS: {
const propElements = action.payload; const propElements = action.payload;
const elementsSplitted: ElementsSplitted = { const nextElements: NextElements = {
nodeElements: [], nextNodes: [],
edgeElements: [], nextEdges: [],
}; };
const { nodeElements, edgeElements } = propElements.reduce((res, item): ElementsSplitted => { const { nextNodes, nextEdges } = propElements.reduce((res, propElement): NextElements => {
if (isNode(item)) { if (isNode(propElement)) {
res.nodeElements.push(item); let storeNode = state.nodes.find((node) => node.id === propElement.id);
} else if (isEdge(item)) {
res.edgeElements.push(item); // update existing element
if (storeNode) {
const positionChanged =
storeNode.position.x !== propElement.position.x || storeNode.position.y !== propElement.position.y;
const typeChanged = typeof propElement.type !== 'undefined' && propElement.type !== storeNode.type;
storeNode = {
...storeNode,
...propElement,
};
if (positionChanged) {
storeNode.__rf.position = propElement.position;
}
if (typeChanged) {
// we reset the elements dimensions here in order to force a re-calculation of the bounds.
// When the type of a node changes it is possible that the number or positions of handles changes too.
storeNode.__rf.width = null;
}
res.nextNodes.push(storeNode);
} else {
// add new element
res.nextNodes.push(parseNode(propElement, state.nodeExtent));
}
} else if (isEdge(propElement)) {
let storeEdge = state.edges.find((se) => se.id === propElement.id);
if (storeEdge) {
storeEdge = {
...storeEdge,
...propElement,
};
res.nextEdges.push(storeEdge);
} else {
res.nextEdges.push(parseEdge(propElement));
}
} }
return res; return res;
}, elementsSplitted); }, nextElements);
const nextNodes = nodeElements.map((propNode: Node) => {
let storeNode = state.nodes.find((node) => node.id === propNode.id);
// update existing element
if (storeNode) {
const positionChanged =
storeNode.position.x !== propNode.position.x || storeNode.position.y !== propNode.position.y;
const typeChanged = typeof propNode.type !== 'undefined' && propNode.type !== storeNode.type;
storeNode = {
...storeNode,
...propNode,
};
if (positionChanged) {
storeNode.__rf.position = propNode.position;
}
if (typeChanged) {
// we reset the elements dimensions here in order to force a re-calculation of the bounds.
// When the type of a node changes it is possible that the number or positions of handles changes too.
storeNode.__rf.width = null;
}
return storeNode;
} else {
// add new element
return parseNode(propNode, state.nodeExtent);
}
});
const nextEdges = edgeElements.map((propEdge: Edge) => {
let storeEdge = state.edges.find((se) => se.id === propEdge.id);
if (storeEdge) {
return {
...storeEdge,
...propEdge,
};
} else {
return parseEdge(propEdge);
}
});
return { ...state, nodes: nextNodes, edges: nextEdges }; return { ...state, nodes: nextNodes, edges: nextEdges };
} }
@@ -121,7 +115,6 @@ export default function reactFlowReducer(state = initialState, action: ReactFlow
} }
case constants.UPDATE_NODE_POS: { case constants.UPDATE_NODE_POS: {
const { id, pos } = action.payload; const { id, pos } = action.payload;
let position: XYPosition = pos; let position: XYPosition = pos;
if (state.snapToGrid) { if (state.snapToGrid) {