Skip to content

Commit

Permalink
Merge pull request #44 from 4dn-dcic/utk-fix-console-errors
Browse files Browse the repository at this point in the history
CSSTransition Updates to Fix findDOMNode Errors
  • Loading branch information
utku-ozturk authored Aug 27, 2024
2 parents 0ff8cc3 + e6a8ada commit 28ece31
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 61 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
- [View releases on NPM](https://www.npmjs.com/package/@hms-dbmi-bgm/react-workflow-viz?activeTab=versions)
- [View releases on Unpkg](https://unpkg.com/browse/@hms-dbmi-bgm/react-workflow-viz/)

#### 2024-08-27 (v0.1.11)
- CSSTransition in Nodes and Edges was throwing the `findDOMNode is deprecated and will be removed in the next major release. Instead, add a ref directly to the element you want to reference.` during animations and transitions. Forwarding the referenced DOM element by nodeRef and ref props solved the issue.

#### 2023-05-17 (v0.1.9)
- No changes except `package-lock.json` + `package.json` version (new NPM release)

Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hms-dbmi-bgm/react-workflow-viz",
"version": "0.1.10",
"version": "0.1.11",
"description": "React component for visualizing CWL-like workflows and provenance graphs.",
"main": "./dist/react-workflow-viz.min.js",
"unpkg": "./dist/react-workflow-viz.min.js",
Expand Down
10 changes: 3 additions & 7 deletions src/components/Edge.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,6 @@ export default class Edge extends React.Component {
this.state = {
'pathDimension' : this.generatePathDimension()
};

// Alternative implementation of transition -
// adjust pathRef.current `d` attribute manually
this.pathRef = React.createRef();
}

getComputedProperties(props = this.props){
Expand Down Expand Up @@ -390,7 +386,7 @@ export default class Edge extends React.Component {
});
}

const pathElem = this.pathRef.current; // Necessary if using alternate transition approach(es).
const pathElem = this.props.forwardedRef.current; // Necessary if using alternate transition approach(es).
const changeTween = () =>
(t) => {
const nextCoords = [
Expand Down Expand Up @@ -463,7 +459,7 @@ export default class Edge extends React.Component {
}

render(){
const { edge, pathArrows, style } = this.props;
const { edge, pathArrows, style, forwardedRef } = this.props;
const { pathDimension } = this.state;
const { disabled, selected, related, distantlySelected } = this.getComputedProperties();
let markerEnd;
Expand All @@ -479,7 +475,7 @@ export default class Edge extends React.Component {
}

return (
<path d={pathDimension} ref={this.pathRef} className={"edge-path" + (disabled ? ' disabled' : '' )}
<path d={pathDimension} ref={forwardedRef} className={"edge-path" + (disabled ? ' disabled' : '' )}
data-edge-selected={selected || distantlySelected} data-edge-related={related}
data-source={edge.source.name} data-target={edge.target.name} style={style}
markerEnd={markerEnd && "url(#" + markerEnd + ")"} />
Expand Down
81 changes: 50 additions & 31 deletions src/components/EdgesLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,9 @@ export function traceEdges(
};
}


const ForwardedEdge = React.forwardRef((props, ref) => {
return <Edge {...props} forwardedRef={ref} />;
});

export default class EdgesLayer extends React.PureComponent {

Expand Down Expand Up @@ -363,37 +365,39 @@ export default class EdgesLayer extends React.PureComponent {
constructor(props){
super(props);
this.sortedEdges = this.sortedEdges.bind(this);
//this.getAllPathElements = this.getAllPathElements.bind(this);
//this.edgeRefs = [];
// Create refs for each node
this.nodeRefs = {};
}

static edgeOnEnter(nodeRef) {
if (nodeRef.current && nodeRef.current.style) {
nodeRef.current.style.opacity = 0;
}
}

static edgeOnEntering(nodeRef) {
if (nodeRef.current && nodeRef.current.style) {
nodeRef.current.style.opacity = 0;
}
}

static edgeOnEnter(elem) { elem.style.opacity = 0; }
static edgeOnEntering(elem) { elem.style.opacity = 0; }
static edgeOnEntered(elem) { elem.style.opacity = null; /** Allows CSS to override, e.g. .15 opacity for disabled edges */ }
static edgeOnExit(elem) { elem.style.opacity = 0; }
static edgeOnEntered(nodeRef) {
if (nodeRef.current && nodeRef.current.style) {
nodeRef.current.style.opacity = null;
}
}

static edgeOnExit(nodeRef) {
if (nodeRef.current && nodeRef.current.style) {
nodeRef.current.style.opacity = 0;
}
}

sortedEdges = memoize(function(edges, selectedNodes, isNodeDisabled){
const nextEdges = EdgesLayer.sortedEdges(edges, selectedNodes, isNodeDisabled);
// Create new list of refs each time we're updated.
//this.edgeRefs = [];
//_.forEach(nextEdges, ()=>{
// this.edgeRefs.push(React.createRef());
//});
const nextEdges = EdgesLayer.sortedEdges(edges, selectedNodes, isNodeDisabled);;
return nextEdges;
});

// Experimentation with transitioning multiple edges at once within requestAnimationFrame.
// Need to rethink design of this, an array for this.edgeRefs won't work as we need to keep
// state.source.x, state.source.y cached in state and associated w/ each edge.
// Possibly can use object keyed by 'key' string (as determined in render method).
// Keeping for reference.
//
//getAllPathElements(){
// return _.map(this.edgeRefs, function(ref){
// return ref && ref.current && ref.current.pathRef && ref.current.pathRef.current;
// });
//}

pathArrows(){
if (!this.props.pathArrows) return null;
return Edge.pathArrowsMarkers();
Expand Down Expand Up @@ -425,13 +429,28 @@ export default class EdgesLayer extends React.PureComponent {
{
_.map(this.sortedEdges(edges, selectedNode, isNodeDisabled), (edge, index) => {
const key = (edge.source.id || edge.source.name) + "----" + (edge.target.id || edge.target.name);
if (!this.nodeRefs[key]) {
this.nodeRefs[key] = React.createRef();
}
return (
<Transition unmountOnExit mountOnEnter timeout={500} key={key}
onEnter={EdgesLayer.edgeOnEnter} onEntering={EdgesLayer.edgeOnEntering}
onExit={EdgesLayer.edgeOnExit} onEntered={EdgesLayer.edgeOnEntered}>
<Edge {...this.props} {...{ key, edge, edgeCount }}
startX={edge.source.x} startY={edge.source.y}
endX={edge.target.x} endY={edge.target.y} />
<Transition
unmountOnExit
mountOnEnter
timeout={500}
key={key}
onEnter={() => EdgesLayer.edgeOnEnter(this.nodeRefs[key])}
onEntering={() => EdgesLayer.edgeOnEntering(this.nodeRefs[key])}
onEntered={() => EdgesLayer.edgeOnEntered(this.nodeRefs[key])}
onExit={() => EdgesLayer.edgeOnExit(this.nodeRefs[key])}
nodeRef={this.nodeRefs[key]}>
<ForwardedEdge
{...this.props}
{...{ key, edge, edgeCount }}
startX={edge.source.x}
startY={edge.source.y}
endX={edge.target.x}
endY={edge.target.y}
ref={this.nodeRefs[key]} />
</Transition>
);
})
Expand Down
20 changes: 3 additions & 17 deletions src/components/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,21 +96,7 @@ export default class Node extends React.Component {
static isSelected(currentNode, selectedNode){
if (!selectedNode) return false;
if (selectedNode === currentNode) return true;
/*
// We shouldn't need the below and can just rely on a simple reference comparison
// Keeping around for now/reference.
if (typeof selectedNode.name === 'string' && typeof currentNode.name === 'string') {
if (selectedNode.name === currentNode.name){
// Case: IO node (which would have add'l self-generated ID to ensure uniqueness)
if (typeof selectedNode.id === 'string'){
if (selectedNode.id === currentNode.id) return true;
return false;
}
return true;
}
return false;
}
*/

return false;
}

Expand Down Expand Up @@ -230,7 +216,7 @@ export default class Node extends React.Component {
}

render(){
var { node, isNodeDisabled, className, columnWidth, renderNodeElement, selectedNode } = this.props,
var { node, isNodeDisabled, className, columnWidth, renderNodeElement, selectedNode, forwardedRef } = this.props,
disabled = typeof node.disabled !== 'undefined' ? node.disabled : this.isDisabled(node, isNodeDisabled),
isCurrentContext = typeof node.isCurrentContext !== 'undefined' ? node.isCurrentContext : null,
classNameList = ["node", "node-type-" + node.nodeType],
Expand Down Expand Up @@ -258,7 +244,7 @@ export default class Node extends React.Component {
'left' : node.x,
'width' : columnWidth || 100,
'zIndex' : 2 + (node.indexInColumn || 0)
}}>
}} ref={forwardedRef}>
<div className="inner" children={renderNodeElement(node, visibleNodeProps)}
{..._.pick(this.props, 'onMouseEnter', 'onMouseLeave')} onClick={disabled ? null : this.props.onClick} />
</div>
Expand Down
12 changes: 10 additions & 2 deletions src/components/NodesLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export default class NodesLayer extends React.PureComponent {
countInActiveContext: memoize(NodesLayer.countInActiveContext),
lastActiveContextNode: memoize(NodesLayer.lastActiveContextNode)
};
this.nodeRefs = {};
}

renderNodeElements(){
Expand All @@ -59,9 +60,12 @@ export default class NodesLayer extends React.PureComponent {
'className' : nodeClassName
}
);
if (!this.nodeRefs[nodeProps.key]) {
this.nodeRefs[nodeProps.key] = React.createRef();
}
return (
<CSSTransition classNames="workflow-node-transition" unmountOnExit timeout={500} key={nodeProps.key}>
<Node {...nodeProps} />
<CSSTransition classNames="workflow-node-transition" unmountOnExit timeout={500} key={nodeProps.key} nodeRef={this.nodeRefs[nodeProps.key]}>
<ForwardedNode {...nodeProps} ref={this.nodeRefs[nodeProps.key]} />
</CSSTransition>
);
});
Expand All @@ -83,3 +87,7 @@ export default class NodesLayer extends React.PureComponent {
}

}

const ForwardedNode = React.forwardRef((props, ref) => {
return <Node {...props} forwardedRef={ref} />;
});

0 comments on commit 28ece31

Please sign in to comment.