refactor(elements): simplfy node and edge handling

This commit is contained in:
moklick
2019-07-31 18:01:15 +02:00
parent 3403203adb
commit e348cccc76
14 changed files with 4105 additions and 4157 deletions

4010
dist/ReactGraph.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -212,7 +212,7 @@ var parent = module.bundle.parent;
if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') {
var hostname = "" || location.hostname;
var protocol = location.protocol === 'https:' ? 'wss' : 'ws';
var ws = new WebSocket(protocol + '://' + hostname + ':' + "58449" + '/');
var ws = new WebSocket(protocol + '://' + hostname + ':' + "53462" + '/');
ws.onmessage = function (event) {
checkedAssets = {};

View File

@@ -1,6 +1,6 @@
import React from 'react';
import React, { memo } from 'react';
export default (props) => {
export default memo((props) => {
const { targetNode, sourceNode } = props;
const style = props.style || {};
@@ -26,4 +26,4 @@ export default (props) => {
d={dAttr}
/>
);
};
});

View File

@@ -1,6 +1,6 @@
import React from 'react';
import React, { memo } from 'react';
export default (props) => {
export default memo((props) => {
const { targetNode, sourceNode } = props;
const style = props.style || {};
@@ -20,4 +20,4 @@ export default (props) => {
d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`}
/>
);
};
});

View File

@@ -21,6 +21,7 @@ function renderEdge(e, props, graphContext) {
return (
<EdgeComponent
key={`${e.source}-${e.target}`}
id={e.id}
type={e.type}
sourceNode={sourceNode}
targetNode={targetNode}

View File

@@ -1,14 +1,16 @@
import React, { createContext, useEffect, useReducer, useRef } from 'react';
import React, { createContext, useEffect, useReducer } from 'react';
import PropTypes from 'prop-types';
import isEqual from 'lodash.isequal';
import { reducer, initialState } from '../state';
import { setNodes, setEdges } from '../state/actions';
import { parseElement, isNode, isEdge } from '../graph-utils';
export const GraphContext = createContext({});
export const Provider = (props) => {
const {
elements,
children,
onConnect
} = props;
@@ -16,7 +18,10 @@ export const Provider = (props) => {
const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
const nextNodes = props.nodes.map(propNode => {
const nodes = elements.filter(isNode);
const edges = elements.filter(isEdge).map(parseElement);
const nextNodes = nodes.map(propNode => {
const existingNode = state.nodes.find(n => n.id === propNode.id);
if (existingNode) {
@@ -29,22 +34,21 @@ export const Provider = (props) => {
};
}
return propNode;
return parseElement(propNode);
});
const nodesChanged = !isEqual(state.nodes, nextNodes);
const edgesChanged = !isEqual(state.edges, props.edges);
const edgesChanged = !isEqual(state.edges, edges);
if (nodesChanged) {
dispatch(setNodes(nextNodes));
}
if (edgesChanged) {
dispatch(setEdges(props.edges));
dispatch(setEdges(edges));
}
});
const graphContext = {
state,
dispatch,
@@ -63,11 +67,9 @@ export const Provider = (props) => {
export const { Consumer } = GraphContext;
Provider.propTypes = {
nodes: PropTypes.arrayOf(PropTypes.object),
edges: PropTypes.arrayOf(PropTypes.object)
elements: PropTypes.arrayOf(PropTypes.object)
};
Provider.defaultProps = {
nodes: [],
edges: []
elements: [],
};

View File

@@ -66,7 +66,7 @@ const onNodeClick = (evt, { onClick, dispatch, id, type, position, data }) => {
const node = { id, type, position, data }
dispatch(setSelectedElements(node));
dispatch(setSelectedElements({ id, type }));
onClick(node);
};

View File

@@ -25,6 +25,7 @@ function renderNode(d, props, graphContext) {
transform={graphContext.state.transform}
getNodeById={graphContext.getNodeById}
selectedElements={graphContext.state.selectedElements}
style={d.style}
/>
);
}

View File

@@ -1,12 +1,10 @@
import React, { PureComponent } from 'react';
import isEqual from 'lodash.isequal';
if (process.env.NODE_ENV !== 'production') {
const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React);
}
import { parseElements, isNode, isEdge } from '../graph-utils';
import GraphView from '../GraphView';
import GlobalKeyHandler from '../GlobalKeyHandler';
import { Provider } from '../GraphContext';
@@ -28,42 +26,18 @@ class ReactGraph extends PureComponent {
this.nodeTypes = createNodeTypes(props.nodeTypes);
this.edgeTypes = createEdgeTypes(props.edgeTypes);
this.state = {
nodes: [],
edges: []
};
}
componentDidMount() {
this.updateElements(this.props.elements);
}
componentDidUpdate(prevProps) {
if (!isEqual(prevProps.elements, this.props.elements)) {
this.updateElements(this.props.elements);
}
}
updateElements(elements) {
const parsedElements = elements.map(parseElements);
this.setState({
nodes: parsedElements.filter(isNode),
edges: parsedElements.filter(isEdge),
});
}
render() {
const {
style, onElementClick, children, onLoad,
style, onElementClick, elements, children, onLoad,
onMove, onChange, onElementsRemove, onConnect, onNodeDragStop,
connectionLineType, connectionLineStyle
} = this.props;
return (
<div style={style} className="react-graph">
<Provider nodes={this.state.nodes} edges={this.state.edges} onConnect={onConnect}>
<Provider elements={elements} onConnect={onConnect}>
<GraphView
onLoad={onLoad}
onMove={onMove}

View File

@@ -23,15 +23,13 @@ export const removeElements = (elements, elementsToRemove) => {
});
};
let internalNodeId = 0;
const getEdgeId = (e) => `react-graph__edge-${e.source}-${e.target}`;
const getId = () => internalNodeId++;
export const parseElements = (e) => {
export const parseElement = (e) => {
e.type = e.type || 'default';
e.id = e.id ? e.id : getId();
if (isEdge(e)) {
e.id = e.id ? e.id.toString() : getEdgeId(e);
return e;
}
@@ -132,5 +130,6 @@ export default {
separateElements,
getBoundingBox,
graphPosToZoomedPos,
getConnectedEdges
getConnectedEdges,
parseElement
};

View File

@@ -5,7 +5,7 @@ export default ReactGraph;
export { default as SourceHandle } from './NodeRenderer/HandleTypes/SourceHandle';
export { default as TargetHandle } from './NodeRenderer/HandleTypes/TargetHandle';
export {
export {
isNode,
isEdge,
removeElements,

View File

@@ -1,4 +1,5 @@
import { zoomIdentity } from 'd3-zoom';
import isEqual from 'lodash.isequal';
import { getBoundingBox, getNodesInside, getConnectedEdges } from '../graph-utils';
@@ -101,10 +102,13 @@ export const reducer = (state, action) => {
const selectedNodes = getNodesInside(state.nodes, action.payload.selection, state.transform);
const selectedEdges = getConnectedEdges(selectedNodes, state.edges);
const nextSelectedElements = [...selectedNodes, ...selectedEdges];
const selectedElementsUpdated = !isEqual(nextSelectedElements, state.selectedElements);
return {
...state,
...action.payload,
selectedElements: [...selectedNodes, ...selectedEdges]
selectedElements: selectedElementsUpdated ? nextSelectedElements: state.selectedElements
};
}
case SET_NODES_SELECTION: {