Integrating D3.js and React.js. Facing chart overlapping on data update

By Pratik

I’m trying to integrate D3 and React. New to both the technologies.
So my problem statement is to enter the input data which then results into forming an Array of data. This collection of data I’m putting into bar-chart visualisation.

The App component looks like :

class App extends Component {
constructor(props) {
  super(props);
  this.state = {
    chart_data: []
  }
this.setData = this.setData.bind(this);
}
setData(data) {
  this.setState({chart_data: data});
}
render() {
  return (
    <div>
      <Form setData={this.setData} />
      <Chart uid="chart-1" data={this.state.chart_data} />
    </div>
  );
}
}
export default App;

The Chart Component looks like :

import React, { Component } from 'react';
import * as d3 from 'd3';
class Chart extends Component {
componentDidMount() {
  d3.select(this.node).append("svg").attr("height", 400).attr("width", 440)
}
componentDidUpdate() {
  this.renderChart(this.props.data);
}
renderChart(data) {
  var dataArray = data;
  var minDataElem = Math.min(...dataArray);
  var maxDataElem = Math.max(...dataArray);
  var width = 400;
  var scaleHeight = d3.scaleLinear()
                      .domain([minDataElem, maxDataElem])
                      .range([1, 200]);
  var scaleWidth = d3.scaleBand()
                      .domain(dataArray.map(function (d, i) { return i; }))
                      .rangeRound([0, width])
                      .paddingInner(0.1)
                      .paddingOuter(0.5);
  var yAxisScale = d3.scaleLinear()
                     .domain([minDataElem, maxDataElem])
                     .range([200, 0]);
  var xAxisScale = d3.scaleLinear()
                     .domain([0, dataArray.length])
                     .range([0, width])
  var yAxis = d3.axisLeft(yAxisScale);
  var xAxis = d3.axisBottom(xAxisScale).ticks(dataArray.length);
  var barCanvas = d3.select("svg")
                    .append("g").attr("transform", "translate(50, 50)");;
  barCanvas.call(yAxis);
  barCanvas.append("g")
              .attr("transform", "translate(0, 200)")
            .call(xAxis);
  barCanvas.selectAll("rect")
           .data(dataArray, function(d, i) { return '' + i + '-' + d; })
           .enter()
           .append("rect")
              .attr("height", function(d) { return scaleHeight(d); })
              .attr("width", function () { return scaleWidth.bandwidth(); })
              .attr("fill", "steelblue")
              .attr("x", function(d, i) { return scaleWidth(i); })
              .attr("y", function(d) { return (200-scaleHeight(d)) });
  barCanvas.exit().remove();
}
render() {
  return <div ref={node => this.node = node} className={this.props.uid} >
  </div>;
}
}
export default Chart;

As, the App component also embeds Form Component, Here’s the short description of it: It contains 3 input fields – Principle Amount, Rate of Interest and Number of Years. These input fields results into Future Value evaluation which is calculated with some Mathematical Formula, on Submit. The function which evaluates this returns an Array of Future Value which then passed as props to Chart component which renders the Chart.

Now, the problem I’m facing on data update(i.e. If after rendering chart for the first time by inputting first set of data, I enter another set of input data and hit the submit button) I get the overlapping of chart.

Instead I want the first chart data to get updated. I think this issue is related to D3 enter update exit.

The workaround works but entirely flushing the chart and re-rendering it. But that misses the entire point of integrating D3 and React.

How can we fix this?

Source: Stack Overflow

    

Share it with your friends!

    Fatal error: Uncaught Exception: 12: REST API is deprecated for versions v2.1 and higher (12) thrown in /home/content/19/9652219/html/wp-content/plugins/seo-facebook-comments/facebook/base_facebook.php on line 1273