Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-hooks and d3.forceSimulation

I'm having some issues with my forceSimulation in React (using Hooks). The problem is that whenever data is changed the position of each bubble is translated into the middle of the screen, rather than considering its previous position (see gif), making the bubbles jump in an annoying way.

I do not have much experience with forceSimulation, d3 and react-hooks in conjunction, and its hard to find any similar examples; so I would really appreciate any guidance.

import React, { useEffect, useRef } from 'react'
import { forceSimulation, forceX, forceY, forceCollide, select } from 'd3'

export default function Bubbles({ data, width, height }) {
  const ref = useRef()
  const svg = select(ref.current)

  useEffect(() => {
    const simulation = forceSimulation(data)
      .force('x', forceX().strength(0.02))
      .force('y', forceY().strength(0.02))
      .force(
        'collide',
        forceCollide((d) => {
          return d.value * 20 + 3
        }).strength(0.3)
      )
    simulation.on('tick', () =>
      svg
        .selectAll('circle')
        .data(data)
        .join('circle')
        .style('fill', () => 'red')
        .attr('cx', (d) => d.x)
        .attr('cy', (d) => d.y)
        .attr('r', (d) => d.value * 20)
    )
  }, [data])

  return (
    <svg
      viewBox={`${-width / 2} ${-height / 2} ${height} ${width}`}
      width={width}
      height={height}
      ref={ref}
      style={{
        marginRight: '0px',
        marginLeft: '0px'
      }}
    ></svg>
  )
}

enter image description here

like image 219
howtopythonpls Avatar asked Oct 26 '25 12:10

howtopythonpls


1 Answers

I think the problem here is that React renders the SVG, but D3 renders the circles. When React re-renders on update it creates the SVG and discards any children because it doesn't know about them.

Thus the data can't be bound to the DOM in the usual D3 way, but should be stored in your React component's state.

like image 198
Nate Wessel Avatar answered Oct 29 '25 03:10

Nate Wessel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!