Massoud Mazar

Sharing The Knowledge

NAVIGATION - SEARCH

Using D3 charting components with ReactJS

ReactJS seems to have picked up some die hard fans and recently I was looking at how to use D3 for charting in a React based UI. There are a few implementation of some of the D3 libraries and I picked reactd3 for my experiment. The documentation site has some examples of how this can be done, but they all use ReactDOM.render to directly render to a DOM element you have put in your HTML template. My preferred approach is to not rely on existence of a predefined HTML tag in the template, but use an element which is rendered by my chart component. Here is what I ended up doing:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Paper from 'material-ui/Paper';
import { LineChart } from 'react-d3-basic';

export class SeriesChart extends Component {

  constructor(...args) {
    super(...args);

    this.chartStyle = {
        height: "100%"
    };
  }

  handleResize(e) {
      let elem = ReactDOM.findDOMNode(this);;
      this.setState({
          width: elem.offsetWidth,
          height: elem.offsetHeight
      });
  }

  componentWillReceiveProps() {
    this.handleResize();
  }

  componentDidUpdate() {
    let chartData = this.props.series.map(function(obj, idx){
      return {'index': idx, 'date': obj[0], 'value': obj[1]};
     }
    );

    let margins = {left: 80, right: 50, top: 50, bottom: 50};

    let chartSeries =  [
        {
          field: 'value',
          name: 'value',
          color: '#ff7f0e',
          style: {
            "strokeWidth": 2,
            "strokeOpacity": .2,
            "fillOpacity": .2
          }
        }
      ];

    let x = function(d) {
        return d.date;
      };

    ReactDOM.render(
        <LineChart
          yLabel={this.props.title}
          width={this.state.width}
          height={this.state.height}
          margins={margins}
          showLegend={false}
          data={chartData}
          chartSeries={chartSeries}
          x={x}
          xScale='time'
        />
      , document.getElementById(this.props.title +'-SeriesChart')
      );
  }

  render() {
    return (
      <Paper id={this.props.title +'-SeriesChart'} style={this.chartStyle} zDepth={2}>
      </Paper>
    );
  }

}

In this example, I'm using material-ui library which provides the Paper component above. render function of my react component renders the Paper, and assigns a unique id to it. Then componentDidUpdate uses the ReactDOM.render to render the chart to the div created by Paper.

Add comment