Search code examples
reactjsreact-chartjscolumn-chart

React-charts not updating with data


I am new react, and want to display charts in my component, wherein the the data should be populated from the API response.

My sample API response is:

{
    "result": 1,
    "data": [
        {
            "data1": "1272.00",
            "data2": "1183.00",
            "price": "131.00"
        },
        {
            "data1": "1328.00",
            "data2": "1468.00",
            "price": "132.00"
        },
        {
            "data1": "1829.00",
            "data2": "1445.00",
            "price": "133.00"
        },
        {
            "data1": "1089.00",
            "data2": "968.00",
            "price": "134.00"
        },
        {
            "data1": "16700.00",
            "data2": "20901.00",
            "price": "135.00"
        },
        {
            "data1": "804.00",
            "data2": "1110.00",
            "price": "136.00"
        },
    ]
}

I want price to be in YAxis and multiple data, i.e., data1 and data2 fields on XAxis.

React code: (implementing just one)

import React, { Component } from "react";
import Sidebar from "./Sidebar";
import { Chart } from "react-charts";
import axios from "axios";

const qs = require("qs");

class Home extends Component {
  state = {
    datelist: [],
    chart_data: []
  };

  componentDidMount() {
    this.getDatesList();
  }

  getDatesList() {
    axios.get("http://127.0.0.1:8000/dateslist/").then(res => {
      if (res.data.result === 1) {
        this.setState({ datelist: res.data.data });
      } else {
        this.setState({ datelist: [] });
      }
    });
  }

  handleChange = event => {
    var dateval = event.target.value;
    axios
      .post(`http://127.0.0.1:8000/pricedata/`, qs.stringify({ date: dateval }))
      .then(res => {
        if (res.data.result === 1) {
          this.setState({
            chart_data: [
              {
                label: "Strike",
                data: res.data.data
              }
            ]
          });
        } else {
          this.setState({ chart_data: [] });
        }
      });
  };

  render() {
    return (
      <div className="container container_padding">
        <div className="row">
          <Sidebar />
          <div className="col-md-9 col-sm-9 col-xs-12">
            <select
              className="form-control"
              style={{ width: "120px", marginBottom: "10px" }}
              onChange={this.handleChange}
            >
              {this.state.datelist.map((date, i) => (
                <option value={date} key={i}>
                  {date}
                </option>
              ))}
            </select>
            <div
              style={{
                width: "400px",
                height: "300px"
              }}
            >
              <Chart
                data={this.state.chart_data}
                series={{ type: "bar" }}
                axes={[
                  { primary: true, type: "ordinal", position: "bottom" },
                  { type: "linear", position: "left", stacked: true }
                ]}
                primaryCursor
                tooltip
              />
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default Home;

The state is updated, but chart is not displayed.

Note: I have installed charts library as - npm i --save react-chartjs-2 chart.js

What am I missing? How should I correctly populate data that is to be shown?

Thanks in advance.


Solution

  • I have looked into the response found that you are passing data prop to chart as follows:

    {
        label: "Strike",
        data: [
        {
            "data1": "1272.00",
            "data2": "1183.00",
            "price": "131.00"
        },
        {
            "data1": "1328.00",
            "data2": "1468.00",
            "price": "132.00"
        },
      ]
    }
    

    which is apparently not correct, in the react-charts doc you can see it accepts the data in the following pattern:

     [
        {
          label: "Series 1",
          data: [[0, 1], [1, 2], [2, 4], [3, 2], [4, 7]]
        },
        {
          label: "Series 2",
          data: [[0, 3], [1, 1], [2, 5], [3, 6], [4, 4]]
        }
      ]
    

    So to make your code work you need to manipulate the response of your API call to match the pattern.

    It can be done by changing the following lines of code:

    handleChange = event => {
        var dateval = event.target.value;
        axios
          .post(`http://127.0.0.1:8000/pricedata/`, qs.stringify({ date: dateval }))
          .then(res => {
            if (res.data.result === 1) {
              this.setState({
                chart_data: [
                  {
                    label: "Strike",
                    data: res.data.data.map(Object.values)
                  }
                ]
              });
            } else {
              this.setState({ chart_data: [] });
            }
          });
      };