Data-Driven Documents (D3.js) is currently my favoured charting library for producing interactive SVG visualisations. Typically, I chose to use it in combination with NVD3. It provides a higher level library of re-usable charts and chart components for D3.
Another JavaScript library that has taken my interest recently is React by Facebook. It aims to be just the View, or V in MVC, for building rich web application user interfaces.
Why React?
Two reasons that I find it of interest are firstly due to the implementation of a virtual DOM allowing very efficient and high performance browser DOM manipulation. This also allows a React JavaScript application to be entirely rendered on the server when using Node.js for the initial page load or SEO benefits. Secondly, React comes with an XML-like syntax called JSX that allows you to write React components and then compose them within your view code as if they were HTML tags. Much as web components - and libraries like Polymer - are aiming for. Except that you can use JSX with React today.
The example taken from React’s homepage illustrates this point, with the <HelloMessage /> component being appended to a DOM node.
The JSX compiler converts the XML syntax to vanilla JavaScript function calls. You can use React without JSX, but I think it’s a really good feature. The JSX compilation can be configured as part of a Grunt build or watch task or by referencing the JSXTransformer.js script for runtime compilation during development.
Reusable charts with React components
Inspiration for combining React with D3 came from reading the following two blog posts where AngularJS was used as a part replacement for D3.
In these articles, AngularJS was used to manipulate the SVG elements, rather than D3.js. It had been relegated to providing the axis scales, calculating shape dimensions and path coordinates.
I was convinced that React could take Angular’s place. Bringing with it the benefits of the web component style charting tags that the JSX syntax would allow me to create.
This would allow me to specify my chart component in the domain and terms of charting: Chart, Bar, Line and DataSeries. Rather than the actual implementation detail of SVG elements such as g, path, rect.
Baby steps to creating a reusable Bar chart
Getting started, I created a static HTML file and added a reference to React and its JSX compiler, D3.js and Underscore.js in the <head /> of the page.
The body of the document simply contained the <div /> that would act as the target DOM node for React to use as the mount point.
Then I created a number of React components that would encapsulate the different elements needed to build a bar chart. These components were wrapped inside <script /> tag with the type text/jsx so that the JSX compiler would compile them on-the-fly and convert them into vanilla JavaScript function calls.
This began with a Chart component to render a container svg element with a given size.
Chart
Next up, a component for each individual Bar to render an SVG rect element.
Bar
Then came a DataSeries component to take an array of values and create a collection of Bars for the chart.
Here I used D3 to create the scales for both x and y axis. This allowed mapping the range of the input domain (values from the data array) to the output range (the available chart area).
Data Series
Finally, a BarChart component was created and used to build the Chart and its child DataSeries with the data array and bar colouring. This was then rendered using React and added to the DOM via the getElementById selector.
This gave me a taster of what could be acheived using React with D3. The end goal was to create a set of reusable charting components that could be composed to create a bar chart.
More importantly, the JSX within the Chart component actually looked like it was describing a bar chart. Rather than dealing with an SVG and shapes - the mechanics of the implementation. Those are details that should be hidden away from the consumer.
Stacked bar chart
Next up I was interested in create a stacked bar chart, composed of a number of data series. I was able to reuse the Chart and Bar components, along with a reworked DataSeries that handled multiple series.
Finally, I attempted a third chart, a multi-series line chart. Here I created a new Line component, in place of the existing Bar, to create an SVG path element.
D3 was used to create the path coordinates for a given data series set of (x,y) coordinates.
Line
Data Series
The resultant LineChart component with multiple DataSeries and the corresponding data series values.
Line Chart
Multi series Line chart component rendered by React
If web components are the future of web application development then React provides a reasonable stepping stone towards that future.
From this journey I saw a glimpse of the power of reusable components that can be built. An approach similar to these snippets could be taken forward and used to create the next generation, component-based and easy to use charting library.