Mojo
Mojo

Reputation: 518

React and Chartjs not updating from dynamic data through api

I am Using React and chartjs for the project. where I receive data for chartjs from API call. There are radio buttons on screen when user selects any radio button API call is made and new data is displayed on chart. But the issue is when ever one hover over chart it toggles between previews data and recent data. I know that update() function will help it but I am not sure where to call update() in my case.

class CountByUserGraph extends React.Component {
  constructor() {
    super();
    this.state = { selectedOption: "A" };
  }

  componentDidMount() {
    this.makeApiCall();
  }

  makeApiCall = () => {
    countByUserGraph(this.state.selectedOption) // API CALL
      .then(response => {
        // recieves data
        this.getChartData(data);
      })
      .catch(err => console.log(err));
  };
  getChartData = data => {
    let myChart = document.getElementById("myChart0").getContext("2d");
    const CountValue = data.map(a => a.countValue);
    const CountMonth = data.map(a => a.month);
    var data = {
      labels: CountMonth,
      datasets: [
        {
          label: "Count",
          data: CountValue
        }
      ]
    };

    var option = {
      responsive: true
      // Options
    };

    let massPopChart = new Chart.Line(myChart, { data: data, options: option });
  };

  handleOptionChange = changeEvent => {
    this.setState({ selectedOption: changeEvent.target.value }, function() {
      this.makeApiCall();
    });
  };

  render() {
    return (
      <div>
        <form className="graph-filter">
          <div>
            <input
              type="radio"
              id="A"
              name="A"
              checked={this.state.selectedOption === "A"}
              onClick={this.handleOptionChange}
              value="A"
            />
            <label htmlFor="A">A</label>
          </div>

          <div>
            <input
              type="radio"
              id="B"
              name="B"
              checked={this.state.selectedOption === "B"}
              onClick={this.handleOptionChange}
              value="B"
            />
            <label htmlFor="B">B</label>
          </div>
        </form>
        <canvas id="myChart0"></canvas>
      </div>
    );
  }
}

Upvotes: 0

Views: 520

Answers (2)

Johnson Cherian
Johnson Cherian

Reputation: 643

You can attach the map referance to the class and once data changes use this referance. Modified your code.

class CountByUserGraph extends React.Component {

  this.massPopChart;

  constructor() {
    super();
    this.state = { selectedOption: "A" };
  }

  componentDidMount() {
    this.makeApiCall();
  }

  makeApiCall = () => {
    countByUserGraph(this.state.selectedOption) // API CALL
      .then(response => {
        // recieves data
        this.getChartData(data);
      })
      .catch(err => console.log(err));
  };
  getChartData = data => {
    let myChart = document.getElementById("myChart0").getContext("2d");
    const CountValue = data.map(a => a.countValue);
    const CountMonth = data.map(a => a.month);
    var data = {
      labels: CountMonth,
      datasets: [
        {
          label: "Count",
          data: CountValue
        }
      ]
    };

    var option = {
      responsive: true
      // Options
    };

    if(this.massPopChart){
       massPopChart.data = data;
       //massPopChart.config.data = data; //use this if above code does not work
       massPopChart.update();
    }
    else{
       this.massPopChart = new Chart.Line(myChart, { data: data, options: option });
    } 
  };

  handleOptionChange = changeEvent => {
    this.setState({ selectedOption: changeEvent.target.value }, function() {
      this.makeApiCall();
    });
  };

  render() {
    return (
      <div>
        <form className="graph-filter">
          <div>
            <input
              type="radio"
              id="A"
              name="A"
              checked={this.state.selectedOption === "A"}
              onClick={this.handleOptionChange}
              value="A"
            />
            <label htmlFor="A">A</label>
          </div>

          <div>
            <input
              type="radio"
              id="B"
              name="B"
              checked={this.state.selectedOption === "B"}
              onClick={this.handleOptionChange}
              value="B"
            />
            <label htmlFor="B">B</label>
          </div>
        </form>
        <canvas id="myChart0"></canvas>
      </div>
    );
  }
}

Upvotes: 1

Beginner
Beginner

Reputation: 9095

you can call the update function, see the docs here

so in your codesnippet you can update the chart as shown below

let massPopChart = new Chart.Line(myChart, { data: data, options: option });
// for example 
massPopChart.options.title.text = 'new title';
massPopChart.update()

similar way you can update the data also.

Upvotes: 0

Related Questions