Karun Siddana
Karun Siddana

Reputation: 11

Unable to plot a bar graph using VictoryBar in React-Redux

I am unable to plot a Bar graph using VictoryBar from the Victory Library for React Components. I am using data from my database to bring the data to the front using Redux and axios middleware.

The payload is getting updated, however the state of the React component only gets larger for instance. Data from 1 country gives an array of objects = 26. When I click a button again, it concatenates the Object to now be 52 Array of Objects. This skews the graph as it is not refreshing the data.


    import React, { Component } from 'react';
    import { connect } from 'react-redux';
    import { bindActionCreators } from 'redux';
    import { Link } from 'react-router';
    import { VictoryChart } from 'victory-chart';
    import { VictoryLine } from 'victory-line';
    import { VictoryAxis } from 'victory-axis';
    import { VictoryBar } from 'victory-bar';
    import { getWaterData } from '../actions/get_water_data';
    import CountryList from '../containers/countryList';

    // console.log('Printing the Water Data', waterData);

    var plottingData = [
      { x: '1990', y: 0 },
      { x: '1992', y: 0 },
      { x: '1994', y: 0 },
      { x: '1996', y: 0 },
      { x: '1998', y: 0 },
    ];
    var processWaterData;

    class VictoryPlots extends Component {
      constructor(props) {
        super(props);
        getWaterData();
        this.update = this.update.bind(this);
        this.state = {
          processed: plottingData,
          count: 2,
          countryId: 1,
          // waterData: getWaterData(),
        };

      }

      processingData() {
        processWaterData = [];

        for (var i = 0; i < this.props.waterData.length; i++) {
          processWaterData.push({x: this.props.waterData[i].year, y: this.props.waterData[i].value });
        }

        // return processWaterData;
        this.setState({ processed: processWaterData}, function() {
          console.log("SET State", this.state.processed);
        });

      }

      // data= { this.state.data } />
      // this.props.getWaterData();

      onInputChange(pCountry) {
        this.setState({ processed: [{x:'1990', y: 100}] });
        this.setState({countryId: pCountry}, function() {
          console.log("countryID: ", this.state.countryId);
        });

      }

      render() {
        return (
          <div>

            <div>
              <input value = { this.state.countryId }
              onChange = { event => this.onInputChange(event.target.value)} />
            </div>

          <Link to="/">Main</Link>

          <button onClick = { this.processingData.bind(this) } >
          Plot Graph
          </button>

          <button onClick = { () => { this.props.getWaterData(this.state.countryId);}}>
          Water Data
          </button>


          <VictoryChart >
            <VictoryBar
              data = { this.state.processed }
              dataAttributes= {[
              {fill: "cornflowerblue"}
              ]}
              />
          </VictoryChart>
        </div>
        );

      }
    }; // End of Component

    function mapStateToProps({ waterData }) {
      // console.log('WATER STATE:', { waterData });
      return { waterData };
    }

    function mapDispatchToProps(dispatch) {
      return bindActionCreators({ getWaterData: getWaterData }, dispatch);
    }

    export default connect(mapStateToProps, mapDispatchToProps)(VictoryPlots);

The VictoryBar: VictoryBar Chart for React

I am not sure how to update the state of the chart, so that the charts update, as I update the input in the Input Box. I am using this.state.processed to update the information in the VictoryBar. this.props.waterData is the data received from the Redux Promise, which comes back with the right data for each country, but then it is getting concatenated to the this.state.waterData, everytime I click on Plot Graph. I'd like it to generate a new plot, everytime I click on Plot Graph.


That was my mistake, I had already fixed that and tried a bunch of ways of updating the state of the component upon click a Plot Graph Button. For more clarity I will paste in my action reducer, and perhaps a screenshot of what I am trying to accomplish here.

Action Reducer (get_water_data.js)

    import axios from 'axios';

    // Send action to server
    export const GET_WATER_DATA = 'GET_WATER_DATA';

    export function getWaterData(pCountryId) {
      // console.log('Calling Water Data Function');

      const url = '//localhost:3001/api/statistics/' + pCountryId;
      // console.log(url);
      const request = axios.get(url);

      // console.log('PROMISE:', request.data);

      return {
        type: GET_WATER_DATA,
        payload: request,
      };
    }

Updated Code that works, however I am mutating the array and I am using splice, which is not the correct way to render new data on the screen, everytime I click on Plot Graph. I am looking to implement this the correct way, and I don't think I know how.

    processingData() {
      var processWaterData = []

      for (var i = 0; i < this.props.waterData.length; i++) {
        processWaterData.push({x: this.props.waterData[i].year, y: this.props.waterData[i].value });
      }

      this.setState({ processed: processWaterData}, function() {
        // console.log("processed info after: ", this.props.waterData);
        if (this.props.waterData.length > 1) {
          // console.log("Length of the waterData:", this.props.waterData.length);
          this.props.waterData.splice(0, this.props.waterData.length);
        }
      });
    }

VictoryBar Chart showing Improved Water Resources from Countries

Upvotes: 1

Views: 1023

Answers (1)

Jake Haller-Roby
Jake Haller-Roby

Reputation: 6427

Looks like a simple typo:

// return processWaterData;
    this.setState({ processed: processed}, function() {

should be:

// return processWaterData;
    this.setState({ processed: processWaterData}, function() {

Upvotes: 1

Related Questions