If you’re planning to build a React app with more than a few simple data visualizations, you’ll probably want to pick an approach that:\n\n* is well-documented, proven, and under active development\n* has a relatively expressive interface– meaning it lets you write custom data graphics with just enough verbosity to express what you want\n* plays well with React– that is, it doesn’t need to directly mutate the DOM\n* gives you plenty of freedom to customize it to suit your app’s needs and visual style\n\nGiven the above criteria, these are what I’d consider to be the best available options (not in any particular order):\n\n* [https://github.com/d3/d3](https://github.com/d3/d3)\n* [https://github.com/vega/vega](https://github.com/vega/vega)\n* [https://github.com/FormidableLabs/victory](https://github.com/FormidableLabs/victory)\n* [https://github.com/recharts/recharts](https://github.com/recharts/recharts)\n\n> Note: there are a handful of projects like [react-chartjs](https://github.com/reactjs/react-chartjs), [react-d3-components](https://github.com/codesuki/react-d3-components), and others which don’t seem to be as actively-maintained, that provide high-level React chart components. If these suit your app, then of course you could just use them!\n\n### Comparing the Options\n\n#### D3\n\nFirst of all, I’d consider [D3](https://hackernoon.com/tagged/d3) to be the standard library for data visualization on the web. It’s the most-starred result for “data visualization” on Github, leading by 50k stars. To see what it’s capable of, just check out [Mike Bostock’s bl.ocks](https://bl.ocks.org/mbostock).\n\n!(https://hackernoon.com/hn-images/1*widuiFZ2hOAcJfGdYDCaXg.png)\n\n[https://bl.ocks.org/mbostock](https://bl.ocks.org/mbostock)\n\n#### Vega\n\nIt seems like Vega and D3 have comparable expressiveness (it is, after all, a wrapper of D3). The awesome thing about Vega is that it lets you write much of what you could write in D3 in a declarative syntax.\n\n!(https://hackernoon.com/hn-images/1*DI1trGqY8zTCZKK94eVU9Q.png)\n\n[Some Vega examples](https://vega.github.io/vega/examples/)\n\nThe caveat is that the conventional way to use Vega seems to be to let it mutate the DOM. This is similar to the convention for using D3, but soon we’ll see how to use D3’s libraries to scale your data, map it to SVG path data, and then return an element tree, just like you would in any ordinary [React](https://hackernoon.com/tagged/react) component. I’m not sure how you’d do this with Vega.\n\n#### Victory and Recharts\n\nBoth Victory and Recharts expose high-level chart components, as well as some lower level chart “parts” like axes, tooltips, etc. While these certainly play well with React, for the sake of customization and expressiveness I prefer D3’s [“theory of graphics”](https://medium.com/@mbostock/introducing-d3-scale-61980c51545f#---451-526) approach. I think there’s just more you can do when you’re in control of scaling data and rendering vs. being at the mercy of higher level component interfaces.\n\nIt could be that I’m just influenced by the huge number of examples of amazing graphics made using D3, and it may be possible to create graphics that are just as great using Victory and Recharts. Unfortunately though, if I got stuck, I don’t think I’d have as many resources to get help as I would using D3.\n\n### Using D3’s libraries to do everything **_but_** rendering DOM nodes\n\nD3 is comprised of 30 libraries. I’ve scanned through the sources of each of them to figure out which are in some way dependent on the DOM, and which are totally independent of it.\n\nMost (22/30) of the D3 APIs don’t have any functions that come in direct contact with the DOM!\n\n* `[d3-array](https://github.com/d3/d3-array)`\n* `[d3-chord](https://github.com/d3/d3-chord)`\n* `[d3-collection](https://github.com/d3/d3-collection)`\n* `[d3-color](https://github.com/d3/d3-color)`\n* `[d3-dispatch](https://github.com/d3/d3-dispatch)`\n* `[d3-dsv](https://github.com/d3/d3-dsv)`\n* `[d3-ease](https://github.com/d3/d3-ease)`\n* `[d3-force](https://github.com/d3/d3-force)`\n* `[d3-format](https://github.com/d3/d3-format)`\n* `[d3-hierarchy](https://github.com/d3/d3-hierarchy)`\n* `[d3-interpolate](https://github.com/d3/d3-interpolate)`\n* `[d3-path](https://github.com/d3/d3-path)`\n* `[d3-polygon](https://github.com/d3/d3-polygon)`\n* `[d3-quadtree](https://github.com/d3/d3-quadtree)`\n* `[d3-queue](https://github.com/d3/d3-queue)`\n* `[d3-random](https://github.com/d3/d3-random)`\n* `[d3-request](https://github.com/d3/d3-request)`\n* `[d3-scale](https://github.com/d3/d3-scale)`\n* `[d3-time](https://github.com/d3/d3-time)`\n* `[d3-time-format](https://github.com/d3/d3-time-format)`\n* `[d3-timer](https://github.com/d3/d3-timer)`\n* `[d3-voronoi](https://github.com/d3/d3-voronoi)`\n\nThe above APIs can be used to transform your data to a form that can be mapped to the React elements you’ll use to construct your graphic.\n\nBefore we get to an example, we’ll list the (8/30) D3 APIs that _do_ access or mutate the DOM. Some of these _can_ be used with React, with some caveats (e.g., work around a function or two, or carefully use refs to select nodes, and allow D3 to mutate them).\n\n* `[d3-axis](https://github.com/d3/d3-axis)`\n* `[d3-brush](https://github.com/d3/d3-brush)`\n* `[d3-drag](https://github.com/d3/d3-drag)`\n* `[d3-geo](https://github.com/d3/d3-geo)`\n* `[d3-selection](https://github.com/d3/d3-selection)`\n* `[d3-shape](https://github.com/d3/d3-shape)`\n* `[d3-transition](https://github.com/d3/d3-transition)`\n* `[d3-zoom](https://github.com/d3/d3-zoom)`\n\n### Example: Writing a composite spark line / scatter plot component\n\nFor the example, let’s make a simple time series visualization that‘s a composite of a spark line and scatter plot with cartesian axes and some styling.\n\n!(https://hackernoon.com/hn-images/1*XM-UFO2X9IXosUA46glklg.png)\n\nLet’s make this with React and D3!\n\n> Here’s the github repo in case you’d prefer to get right into the source: [https://github.com/AnalyticalFlavorSystems/d3ReactExample](https://github.com/AnalyticalFlavorSystems/d3ReactExample).\n\nThis example chart that I built for one of our apps at Analytical Flavor Systems plots a product’s perceived quality (0–7) for the past 14 days. Here’s the data:\n\n#### Designing the Component Interface\n\nOur `TimeSeriesSparkLineScatterPlot` component should be reusable, so we should design it to take an array of any type of object. To support this, we’ll give it the props `data`, `selectX`, and `selectY`. Since it renders an SVG, we should also give it dimension props `width` and `height`. Its interface now looks something like:\n\n#### Writing the Component\n\nLet’s get right to it… we’ll start by writing a component that takes the props from the interface we came up with.\n\nLooks good! Now let’s generate an SVG path for the spark line and then render a group and path for the spark line.\n\n!(https://hackernoon.com/hn-images/1*x-6TBU5leaRXN902H_0Mnw.png)\n\nThat’s a start :)\n\nThat’s a bit ugly, but it looks accurate. We’ll wait until the end to add styles. Let’s add some axes. Now, remember that `d3-axis` is in the “does mutate the DOM” list… Let’s look at how we can use it in our component:\n\n> **Caveat**: if our data updates, our axes won’t re-render, since we’re using D3 to render them directly into their group nodes when they mount. A workaround might be to **add a** `**key**` **to each axis group that changes when the data is updated**. This would cause their nodes to unmount, and new nodes to mount, and then the axes would be rendered again. Maybe this is a bad idea... I’d appreciate feedback!\n\n!(https://hackernoon.com/hn-images/1*MiLCMmX78xHL7BYZ7Jz28A.png)\n\nHmm….\n\nOkay, so it looks like our y axis is rendering, but its contents are outside the bounds of our SVG. Also, our x axis is at the top?!\n\nThe `[d3-axis](https://github.com/d3/d3-axis#api-reference)` [readme](https://github.com/d3/d3-axis#api-reference) says _“regardless of orientation, axes are always rendered at the origin.”_ The D3 convention for this is to manually add a margin around the content and to translate our y axis down to the bottom.\n\nAdding the margins isn’t really interesting enough to walk through. I wrote a component that handles adding a margin around the content of an SVG, called `[SVGWithMargin](https://github.com/AnalyticalFlavorSystems/d3ReactExample/blob/master/src/components/SVGWithMargin/index.js)`.\n\nGreat! Let’s add a margin around our content and move our x axis to the bottom of the content:\n\n!(https://hackernoon.com/hn-images/1*w-WojXBCsRYkekEb714B3Q.png)\n\nMuch better.\n\nAwesome, now let’s add the scatter plot. We’ll just get scaled points for our data, and we’ll render a circle at each point:\n\n!(https://hackernoon.com/hn-images/1*mlavBqC2NxfueIehL1jOEQ.png)\n\nNice!\n\nThat’s it! Now if we add some class names (take a look at the [finished component file](https://github.com/AnalyticalFlavorSystems/d3ReactExample/blob/master/src/components/TimeSeriesSparkLineScatterPlot/index.js)) as well a bit of CSS:\n\nWe get this:\n\n!(https://hackernoon.com/hn-images/1*XM-UFO2X9IXosUA46glklg.png)\n\nThat was easy!\n\n### Conclusion\n\nMost of the D3 libraries don’t depend on the DOM. This means you can use them with React, React Native, or something totally different.\n\nI hope this entry was enjoyable and informational. If this kind of thing is up your alley, we’re growing our team at [Analytical Flavor Systems](https://www.gastrograph.com/), and we’d be happy to have a conversation ;)\n\nWe’re still in the early stages of exploring what’s possible with D3 and React. I’m very interested in hearing the experiences of others who have done data visualizations in React– feel free to leave a comment, link to a related post you’ve written, or ping me [@danscan on Twitter](https://twitter.com/danscan).\n\n### Inspiration\n\nThanks to [Joel Burget](https://twitter.com/dino_joel) for demonstrating the possibility of using some of D3’s APIs with React in his [_D4_ example repo](https://github.com/joelburget/d4).