Reputation: 23
I have a component which renders a graph using ForceGraph3D from the react-force-graph component library.
I have a button for toggling which highlights the nodes with even ids (id%2==0).
The nodes in the graph do correctly render, however the animation/re-rendering of the whole graph takes place. I want the nodes to stay in the same position, and only have the color attribute change. How do I go about doing this?
I was expecting the nodes to be highlighted upon toggling AND remaining in the same position. Changing the state re-renders the kicks off the animation again.
import React, { useState } from 'react';
import { ForceGraph3D } from 'react-force-graph';
const GraphComponent = () => {
const [highlightEven, setHighlightEven] = useState(false);
// Generate 300 nodes
const numNodes = 300;
const nodes = [...Array(numNodes)].map((_, index) => ({ id: `Node ${index + 1}` }));
// Sample data for the graph
const graphData = {
nodes: nodes,
links: [
{ source: 'Node 1', target: 'Node 2' },
{ source: 'Node 2', target: 'Node 3' },
// Add more links as needed
],
};
// Highlight nodes with even IDs
const highlightedNodes = highlightEven ? nodes.filter((node, index) => (index + 1) % 2 === 0) : [];
return (
<div>
<div>
<button onClick={() => setHighlightEven(!highlightEven)}>
Toggle Highlight Even Nodes
</button>
</div>
<div style={{ height: '500px', width: '100%' }}>
<ForceGraph3D
graphData={graphData}
nodeAutoColorBy="id"
linkColor="#999"
nodeColor={(node) => (highlightedNodes.includes(node) ? 'red' : undefined)}
/>
</div>
</div>
);
};
export default GraphComponent;
Upvotes: 1
Views: 1465
Reputation: 11
You should wrap graphData
around a useMemo
to create a stable reference between renders. Without it, ForceGraph3D
would think it's a brand new object each render, hence why the graph is re-rendering itself.
Here's an example from some of react-force-graph
's sample code which does something similar: Highlight nodes / Sample Code
Here's additional reference for useMemo
- Skipping re-rendering of components
Upvotes: 1