@mootari’s tips sound good. I haven’t tried in a while but I think about two approaches. Either:
Don’t use any of the d3 modules that touch the DOM. No d3-selection, no d3-transition, no d3-axis, no d3-brush, no d3-zoom. Just stuff like d3-scale, d3-array, d3-color, d3-format, d3-random.
Don’t use any React stuff that touches the DOM. Make only a black-box container for the visualization in JSX, attach a ref, pass the ref to D3, and do all the DOM stuff in D3.
D3 has a ton of helpful modules that are related to visualization but don’t actually draw it on the screen; if that’s the stuff you need, go option 1. But it’s also a really expressive and distinctive way of drawing the stuff on the screen; if that’s the stuff you need, go option 2. Things get really messy when you mix them!
d3-force itself doesn’t touch the DOM, I think. But most of the examples you’ll find (like all of Mike Bostock’s) include touching the DOM with D3. If you’re trying to copy and paste examples you find online or need smooth transitions and enter/exits, it might be easier (involve less rewriting) to go option 2. But once you understand how d3-force is updating the attributes of the simulation (like coordinates) and how the examples you see online are using d3-selection to pass those to the DOM as attributes, you can also go option 1 and render the nodes and edges in SVG with JSX.