Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating C3 charts on props change with React

Tags:

reactjs

c3

I am trying to beautify the update of a C3 chart written as a React component when its data change. The data flows to the component from a parent component via its props.

The solutions I have now "works" but do not seem optimal: when new data comes in, the whole chart is regenerated. I would like to transition to the new state (lines moving rather than whole chart updating in blink). The C3 API seem to have lots of method but I cannot find how to reach the chart.

var React = require("react");
var c3 = require("c3");

var ChartDailyRev = React.createClass({
    _renderChart: function (data) {
        var chart = c3.generate({
            bindto: '#chart1',
            data: {
              json: data,
              keys: {
                  x: 'date',
                  value: ['requests', 'revenue']
              },
              type: 'spline',
              types: { 'revenue': 'bar' },
              axes: {
                'requests': 'y',
                'revenue': 'y2'
              }
            },
            axis: {
                x: { type: 'timeseries' },
                y2: { show: true }
            }
        });
    },
    componentDidMount: function () {
        this._renderChart(this.props.data);
    },
    render: function () {
        this._renderChart(this.props.data);
        return (
            <div className="row" id="chart1"></div>
        )
    }
});

module.exports = ChartDailyRev;
like image 648
xav Avatar asked Dec 19 '22 04:12

xav


1 Answers

According to the project's documentation:

By using APIs, you can update the chart after it's been rendered. ... APIs can be called through the object returned from generate().

So the first thing you need to do is save a reference to the chart when you generate it. It's easy enough to attach it directly to the component:

var ChartDailyRev = React.createClass({
    _renderChart: function (data) {
        // save reference to our chart to the instance
        this.chart = c3.generate({
            bindto: '#chart1',
            // ...
        });
    },

    componentDidMount: function () {
        this._renderChart(this.props.data);
    },

    // ...
});

Then, you want to update the chart when the props update; React provides a lifecycle hook called componentWillReceiveProps that runs when the props have changed.

var ChartDailyRev = React.createClass({
    // ...

    componentWillReceiveProps: function (newProps) {
        this.chart.load({
            json: newProps.data
        }); // or whatever API you need
    }
});

(Make sure to remove this._renderChart from your render function.)

like image 95
Michelle Tilley Avatar answered Dec 29 '22 00:12

Michelle Tilley