the_muffin_man
the_muffin_man

Reputation: 23

Avoid complete re-rendering and animation of a force-react-graph component upon state change

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

Answers (1)

Luke
Luke

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

Related Questions