D3 directly manipulates given props
Steps to reporoduce:
- Start example
- Set a breakpoint in
onUpdateNode() - 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. :(
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?
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
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.
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.
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.