4 ms·
Anyone know articles on how to integrate d3 with virtual-dom libraries like ReactJs ?
by thecleaner 7y ago
Anyone know articles on how to integrate d3 with virtual-dom libraries like ReactJs ?
- ahstilde 7y agoIt's covered in the author's book: https://www.newline.co/fullstack-d3#ch-react https://www.newline.co/fullstack-d3#ch-react
- cumwolf 7y agothere's already react/D3 libraries. there's also ReCharts, and ChartJS which are wrappers on d3
- status_quo69 7y agoNo article, but I've done it. You basically have to take on a lot of the creation of the SVG element tags yourself, since having both D3 and React manage the DOM is a bit awkward. However, a lot of D3 functions already give back most of the properties that you need to construct the DOM anyways. For example, the classic sunburst chart (example here: https://observablehq.com/@d3/zoomable-sunburst https://observablehq.com/@d3/zoomable-sunburst) can be constructed from the section of code that contructs and partitions the hierarchy: partition = data => { const root = d3.hierarchy(data) .sum(d => d.value) .sort((a, b) => b.value - a.value); return d3.partition() .size([2 * Math.PI, root.height + 1]) (root); } Some downsides to this: * Zooming is non-trivial, you have to recreate it in React proper * React has to re-render entire hierarchies or massive lists depending on the traversal method that you choose to use for hierarchical datasets (topological or depth first) and React chokes on these pretty easily since they tend to be wide and flat * Quickly changing data sets can't really benefit from memoization or React.memo, since the layouts themselves will constantly change. It makes things a bit awkward when mixing with memoizable data. However, once we got the groundwork down, we never really had to touch it again. It was much easier to maintain than the pure d3 implementation using useEffect or componentDidMount, since we didn't have to deal with any sort of DOM state ourselves any more.
- k__ 7y agoI wrote a bit about it here: https://github.com/kay-is/react-from-zero/blob/master/16-advanced-integration.html https://github.com/kay-is/react-from-zero/blob/master/16-adv...
- wattenberger 7y agostatus_quo69's answer is great, just here to add a few thoughts. This is largely why I wanted to write a post like this - often "using d3.js" is what we think we need to do, but I wanted to show that most of the API is just utility functions. Here are the two modules devoted to manipulating the DOM: https://wattenberger.com/blog/d3#manipulating-the-dom https://wattenberger.com/blog/d3#manipulating-the-dom I recommend (and follow) that you render elements like you normally would, and use things like d3 scales or d3.line() to convert your data into the physical aspects that are needed. I find it really hacky to do it any other way. I want to explore more, but I did a quick test to see which is more performant (letting React render a scatter plot, or letting d3 render a scatter plot), and pure React was 4x faster: https://twitter.com/Wattenberger/status/1123413424678027265 https://twitter.com/Wattenberger/status/1123413424678027265 Of course, this was just one example, but it agrees with my hypothesis. I do have a whole chapter devoted to d3 + React (and one on d3 + Angular) that might be worth checking out. I think it largely comes down to understanding your tools and being able to pick the parts of d3 that will be most useful to you.
- rhodysurf 7y agoI use them together and its awesome. D3 handles all the layout and scaling while react handles the dom. As a mostly native developer this combo has blown my mind. I can make awesome complex viz with like 1/5 the code I would need in say swift.
- zapnuk 7y agoI did it a few months ago without prior knowledge of d3, and little knowledge of React. I tried to keep it simple and have as much manual control as possible, such that I could apply the tips of d3 tutorials. I essentially have a visualization class with an svg, and an update function for all the D3 stuff. The data is handed using props. When the component mounts, or updates I call my own update function which sets the svg size, binds the data, and defines the enter/update/exit actions+transitions. Because I call update in the componentDidUpdate function, I had to catch 'fake' updates where the data hadn't changed, and abstain from state-updates such that I don't end up with infinite update loops. componentDidMount() { this.update(); } componentDidUpdate(prevProps, prevState) { this.update(); } render() { return ( <div ref={this.gridRef} className={"VisContainer"}> <svg className={"VisSVG"} ref={this.svgRef} /> </div> ); } With this rather primitive structure, my biggest problem was with d3. While many tutorial cover the enter/update/exit model, they often don't go in-depth wth the key-function of the data binding. Probably because they often use date of form list<int> for their tutorial. In my case I had more complex data such that I needed to have efficient updates, using the filter function of d3.