Matt16749 Matt16749 - 17 days ago 5
React JSX Question

Updating a D3 Chart within React/Redux

I have a D3(v3) chart within a React Component that is used within a Redux application. What is the best way to handle my D3 chart updating to reflect my Redux store change?

Right now, I have a function within the React component that calls the drawing of the chart and a function that calls the removal of the previous chart as soon as

componentWillUpdate
is called as so:

export default class Chart extends Component {
componentWillUpdate(nextProps) {
this.removePreviousChart();
this.drawChart(nextProps.chartData);
}
removePreviousChart(){
const chart = document.getElementById('chart');
while(chart.hasChildNodes())
chart.removeChild(chart.lastChild);
}
}
drawChart() {
//appends an svg to #chart html element and draws a d3 Chart
}
render(){
this.drawChart();
return(<div id='chart' />)
}
}


Any alternative approaches, pseudocode, ideas, or feedback on how to improve this question would be appreciated.

Answer

The approach you followed seems fine to go with.

componentWillUpdate() is invoked immediately before rendering when new props or state are being received. Use this as an opportunity to perform preparation before an update occurs. This method is not called for the initial render.

Note that you cannot call this.setState() here. If you need to update state in response to a prop change, use componentWillReceiveProps() instead.

Note

componentWillUpdate() will not be invoked if shouldComponentUpdate() returns false.

You can read more from here

If you want to setState() on receiving newProps use componentWillReceiveProps() which is fired for every new props.

Use your Chart API to draw everytime you have new props.

    export default class Chart extends Component {
      componentWillReceiveProps(nextProps) {
       this.removePreviousChart();
       this.drawChart(nextProps.chartData);
      }
      removePreviousChart(){
        const chart = document.getElementById('chart');
        while(chart.hasChildNodes())
          chart.removeChild(chart.lastChild);
        }
      } 
      drawChart(chartData) {
        const chart = document.getElementById('chart'); //fails if DOM not rendered
       //appends an svg to #chart html element and draws a d3 Chart
       //assuming you chart function as Chart(element, data);
        if(chart && chartData){ //draw only if DOM rendered and have chartData
          new Chart(chart, chartData); //calls to draw graph
        }
      }
      render(){
        return(<div id='chart' />)
      }
    }