If you try pairing up D3 with React to create interactive data visualizations, you’ll soon discover that both libraries try to solve the same problem and they both want to be in control of the DOM. While React does this with its DOM diffing approach, D3 does it with its enter-update-exit pattern.
How to avoid them fighting over DOMination and what approach is best? Shirley Wu does a great job dissecting the problem into three possible approaches. In this post I explore a variation of her first approach, by not only using D3 for data calculation but also for building the elements that React will then render to thr DOM. How? By tricking D3 into believing he’s working on the DOM while is not…
We’ll build and use as a reference a simple Sankey diagram builder app:
Check the live demo.
Fake it till you make it
Say hello to react-faux-dom: A DOM-like data structure to be mutated by D3 then rendered to React elements.The idea is rather simple: By tricking D3 into thinking it’s acting on the DOM we can rely on many of its methods to manipulate such structure. React-faux-dom supports selector engine and comes with a partial support for addEventListener, perfect if we want to add element interaction.
To use it is a matter of requiring it to create out fake DOM structures, in the example we create a ‘div’ element.
We can now feed this to D3:
If we would have relied on JSX instead, our code would looked something like:
Once you finish faking it, and it’s time to making it, just return it as a react element to be rendered:
Sankey Diagram, a real example
To put all the pieces together and see this approach in a more concrete example, we’ll be building an interactive App that allows us to construct and edit Sankey’s diagrams.
The approach will be:
- React for structure
- D3 for data calculation
- D3/Faux-DOM for React DOM elements construction
- React for rendering
As Shirley Wu mention, this approach may be good for a react app with a small and simple visualization. It comes with the pro of being Clean and easy and the added benefit of being able to port quickly D3 visualizations to react as we don’t have to refactor them into JSX.
1) React for structure
We are going to use a wrapping React Component to hold the state and methods we may need to pass down to other components that need to be able to update the visualization.
The whole structure could look something like:
On a side note, we’ll be using webpack for our build.
D3 for data calculation
We are going to rely on D3 and its Sankey plugin for the visualization calculation:
D3/Faux-DOM for React DOM elements construction
Now, as we saw earlier, we can just rely on D3 + faux-DOM to build our REACT elements
One interesting thing is that we can register our eventListener directly within the D3 chain, i.e.:
React for rendering
We can now return our faux-dom element by converting back to a react element so that can safely render it
Thoughts and resources
This approach could work pretty well if you want to port quickly some D3 code to react and if you are familiar with D3 more then JSX. Otherwise, a JSX only approach where we rely on D3 only for data calculation and not for DOM manipulation might be clearer, and the code produced perhaps shorter.
In the code comments you can find the JSX alternative to create the react elements, I leave it to you pick your poison.