Open RogerTangos opened 7 years ago
@dunnock I'm at arcarter@csail.mit.edu if you'd like to correspond. (I did a quick search, but couldn't find your email.)
Hi @RogerTangos, good spot! It was not possible in the previous version via props update, just fixed so with version 1.2.17 it should be possible.
I suggest to try to update graph data explicitly in JSX or using React.cloneElement, because React.Components.props is readonly from within react component. React reconciles component when rendering, making sure it does not create new component, rather calling componenDidUpdate, where refresh is handled now.
<Sigma graph={updatedGraphData} settings={{drawEdges:true}}>
<RelativeSize initialSize={15}/>
<RandomizeNodePositions/>
</Sigma>
Hope this helps!
I still have the same problem. When new graph data comes, the old graph goes away but the new one is not rendered. No error is shown in console.
Any insights? I'm running react-sigma version 1.2.17.
Hi @cecampos , I had to rollback the fix, since there is no graph merge function in sigma.js library. Therefore any update to the props was cleaning whole graph and setting up new without coordinates. Approach which @RogerTangos has taken appeared to be better - he is making it manageable via adding graph nodes as react components.
@dunnock, @RogerTangos could you possible share an example of how you managed to get the re-rendering to work?
Hey @jkolbe and @cecampos, It's been a while since I worked on the project that was using this, so my information may be out of date.
In my graph's render function, I iterate over current nodes and then display them.
When the graph receives new properties, it reinitializes..
The nodes of a graph exist as their own components.
It's not an especially elegant solution, but it did work for our purposes (which were to demo).
A tip: when working with React-Sigma, I found that some combinations of sigma settings caused the graph to not render, or to behave in very strange and unintuitive ways. I'd encourage you to find a few sigmaSettings that work for you, and not change them until everything else with your graph is working.
Having the same issue with nodes not updating, and trying to implement @RogerTangos solution. I add the nodes+edges to the graph as react components, but they still dont update when i make changes. Specifically, I'm trying to change the label text. Do I need a hook in the componentWillReceiveProps of the node to call sigma.refresh() or remove+add the node?
@yonahforst I also would suggest you to try <Sigma settings={{clone: false}} ...>
, then each Node to keep a reference to its object, that it has put to sigma.addNode(nodeRef) from within you Node's componentDidMount(). Later in the Node's componentDidUpdate() if you update the nodeRef properties, it should update in the sigma graph. sigma.refresh()
might be required though, I would suggest to try without it initially.
@dunnock - thanks! this seemed to work:
class SigmaNode extends Component {
constructor(props){
super(props);
this.embedProps = this.embedProps.bind(this);
this.node = { ...props }
props.sigma.graph.addNode(this.node)
}
componentWillReceiveProps({ label }) {
Object.assign(this.node, { label })
}
I found a different way that seems to be more performant
class UpdateNodeProps extends React.Component {
componentWillReceiveProps({ sigma, nodes }) {
sigma.graph.nodes().forEach(n => {
var updated = nodes.find(e => e.id == n.id)
Object.assign(n, updated)
})
}
render = () => null
}
....
<Sigma
graph={{ nodes, edges }}
style={{ flex: 1 }}
renderer='canvas'
settings={settings}
onClickNode={this.onClickNode.bind(this)}
onClickStage={this.onClickStage.bind(this)}>
<UpdateNodeProps nodes={nodes}/>
</Sigma>
...
@yonahforst Great! Would you mind adding pull request with this component in /src and new small section in Readme.md? Mutable graph nodes
In my case I was only wanting to update the graph once, after load of data (I couldn't use LoadJSON as I needed to generate an AWS4 signed API call). I worked around this issue a little bit more simply by making the render a ternary based on state, so on the first call (when data isn't loaded) it doesn't even render the sigma, then after that it does once and no need for the above solutions for further updates in my use case. Code here: https://github.com/AcrossTheCloud/TBA21-client/blob/5c33303e436c71832c90f0e91f89fd203808ba1b/src/components/NetworkGraph.tsx I like @yonahforst's approach above for a more general solution and I will look into making a PR if I get a little free time over the Xmas break.
I have found the solution by @yonahforst to work really well.
In my case, I wanted to update the colors and labels of nodes. I found that I had to add an extra line to force sigma to redraw. I know this is documented in the sigma repo, but figured this might be helpful to anyone struggling to get their node props to render immediately.
class UpdateNodeProps extends React.Component {
componentWillReceiveProps({ sigma, nodes }) {
sigma.graph.nodes().forEach((n) => {
var updated = nodes.find((e) => e.id == n.id)
Object.assign(n, updated)
})
// Tell sigma to redraw
sigma.refresh()
}
render = () => null
}
Is there a functional component way of doing this? I attempted to convert the above but it's unclear to me how I can pass the sigma object to my FC as I do not have the legacy React component experience. Any help is appreciated.
const UpdateNodeProps = ({ sigma, nodes }: { sigma: any; nodes: any[] }) => {
useEffect(() => {
sigma.graph.nodes().forEach((n: any) => {
const updated = nodes.find((e) => e.id === n.id);
Object.assign(n, updated);
});
// Tell sigma to redraw
sigma.refresh();
}, [nodes, sigma, sigma.graph.nodes]);
return null;
};
export default UpdateNodeProps;
-------
const sigma = useRef();
<Sigma
ref={sigma}
graph={{ nodes, edges }}
style={{ flex: 1 }}
renderer='canvas'
settings={settings}
onClickNode={this.onClickNode.bind(this)}
onClickStage={this.onClickStage.bind(this)}>
<UpdateNodeProps sigma={sigma} nodes={nodes}/>
</Sigma>
Update on this. Adding ref to Sigma and passing to UpdatedNodeProps seems to work :)
So now that I'm able to update/add new nodes and edges via the above. How can i force nodes to layout again via ForceAtlas2 or Randomize? Right now it seems whatever gets added keeps the original x,y set on the node. I'd like to relayout when new nodes/edges have been added.
Honestly it would be nice just to have Sigma updated when the graph data updates and then have it relayout based on that data. Is that the plan or is this just the way react-sigma will continue to work?
Sorry if this is a noob react question. I'm trying to add and delete nodes and edges from an existing Sigma component. Currently, my component is set up as so:
I can reach into the component and change
Sigma.props.graph
, but have trouble forcing the graph to re-render. How would you recommend doing this?