react-digraph icon indicating copy to clipboard operation
react-digraph copied to clipboard

D3 directly manipulates given props

Open alekseyl1992 opened this issue 8 years ago • 5 comments

Steps to reporoduce:

  1. Start example
  2. Set a breakpoint in onUpdateNode()
  3. Drag a node somewhere

Expected behaviour: graph.nodes[i] === viewNode should evaluate to false so that I have previous state and a new one to apply

Actual behaviour: graph.nodes[i] === viewNode is true which means, that D3 directly changed some parts of the state

First of all: this is discouraged by React documentation: https://facebook.github.io/react/docs/react-component.html#state

Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

And it actually means, that it's impossible to track changes history to provide Undo/Redo functionality. Because there is no previous state available.

The easiest possible solution would be to just make a copy of state before passing it to the GraphView. But it will break selection functionality. :(

alekseyl1992 avatar Sep 03 '17 12:09 alekseyl1992

In my implementation, I'm using immutable.js to manage the root graph state, so I'm effectively passing a copy of the state each time.

How would passing copies of the state break selection functionality?

johnvf avatar Sep 08 '17 21:09 johnvf

Yeah i'am facing the same issue, i have written a redux store with Immutable, when Updating I find the x and y position of a node in previous state is same as the updated position i get

gogoku avatar Nov 23 '17 07:11 gogoku

I'm closing this issue as there is a new version of react-digraph that may have fixed it. Please double-check with v5.2.3+ or check out the latest v4.x.x code and report back.

ajbogh avatar Nov 13 '18 00:11 ajbogh

I think the problem still persists. I do not have to implement the "onUpdateNode" at all.

onUpdateNode = (node) => {
    console.log(node); // this node is already in "graph.nodes" state without calling setState
    console.log(this.state.graph.nodes); // here I can find the node with new "x" and "y".
}

The app works good even with this but it is weird and React strongly warn about mutation a component state directly.

Btw: Still love this library 👍 its can be used for so many use cases.

natocTo avatar Mar 04 '19 08:03 natocTo

Thanks @natocTo for checking.

One possible solution (for react-digraph) is to clone the nodes array. This is likely time consuming, but a possible solution nontheless. Whenever we modify a node we would only modify our copied array, not the original array. This is similar to the way we were heading with the new design, where it contains more state, but it looks like we need to do a little more work.

Please keep in mind that copying arrays of nodes may take a significant portion of time, depending on the size of the graph, so we will have to test carefully to ensure we don't regress too much in rendering speed.

ajbogh avatar Mar 05 '19 22:03 ajbogh