Search code examples
javascriptreactjschart.jschartjs-2.6.0react-chartjs

How to send an array of object as a prop?


I have a state which is an object containing an array and that array contains an object which looks something like this [{"tone":"negative","value":0},{"tone":"neutral","value":91},{"tone":"positive","value":9}].

So I want to plot a bar chart using only the values from this array of objects. I want to send these values to another component which can be used to plot bar charts dynamically. But I'm not sure how to do it. can someone please show how to send the values to the barchart component and use them in the barchart as well?

This is the code

state={
    analysis: {
      tonal: [],
      anxiety: []
    }
}
Analysis = async () => {
    //some api call

      const {
        ...tonalAnalysis
      } = result.scores;

      const tonalArray = Object.entries(tonalAnalysis).reduce(
        (carry, [tone, value]) => [
          ...carry,
          { tone: tone.toLowerCase(), value: parseInt(value) }
        ],
        []
      );

      this.setState({
        analysis: { ...this.state.analysis, tonal: tonalArray }
      });
      console.log("Tonal array" + JSON.stringify(this.state.analysis.tonal)); //console logs `[{"tone":"negative","value":0},{"tone":"neutral","value":91},{"tone":"positive","value":9}]`
  };

render(){
    return {
      <BarCharts/> // confused how to send the values as props here
}

the bar chart component where I will use

import React from "react";

import { Bar } from "react-chartjs-2";

import "./App.css";

class BarCharts extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: {
        labels: [
          negative,
          neutral,
          positive
        ],
        datasets: [
          {
            label: "Value plotting",
            backgroundColor: "rgba(255,99,132,0.2)",
            borderColor: "rgba(255,99,132,1)",
            borderWidth: 1,
            hoverBackgroundColor: "rgba(255,99,132,0.4)",
            hoverBorderColor: "rgba(255,99,132,1)",
            data: [65, 59, 80, 81, 56, 55, 40] //want to use the values here dynamically. Don't want these static values
          }
        ]
      }
    };
  }

  render() {
    const options = {
      responsive: true,
      legend: {
        display: false
      },
      type: "bar"
    };
    return (
      <Bar
        data={this.state.data}
        width={null}
        height={null}
        options={options}
      />
    );
  }
}

export default BarCharts;

Solution

  • You can create a HighChart wrapper component that can be used for any Highchart graphs.

    Note:- every time the data set changes you need to destroy and re-render the graph again in order to make the graph reflect changes.

    
    // @flow
    import * as React from "react";
    import merge from "lodash/merge";
    import Highcharts from "highcharts";
    import isEqual from "lodash/isEqual";
    
    export type Props = {
        config?: Object,
        data: Array<any>,
        onRendered?: () => void
    };
    
    class HighchartWrapper extends React.PureComponent<Props> {
        container: ?HTMLElement;
    
        chart: any;
    
        static defaultProps = {
            config: {},
            onRendered: () => {}
        };
    
        componentDidMount() {
            this.drawChart(this.props);
        }
    
        componentWillReceiveProps(nextProps: Props) {
            const data= [...this.props.data];
    
            if (!isEqual(nextProps.config, this.props.config) || !isEqual(nextProps.data, data)) {
                this.destroyChart();
                this.drawChart(nextProps);
            }
        }
    
        destroyChart() {
            if (this.chart) { 
               this.chart.destroy();
            }
        }
    
        componentWillUnmount() {
            this.destroyChart();
        }
    
        drawChart = (props: Props) => {
            const { config: configProp, data, onRendered } = props;
            if (this.container) {
                let config = merge({}, configProp);
    
                this.chart = new Highcharts.chart(this.container, { ...{ ...config, ...{ series: [...data] } } }, onRendered);
            }
        };
    
        render() {
            return <div ref={ref => (this.container = ref)} />;
        }
    }
    
    export default HighchartWrapper;
    
    

    In order use it for BarChart just pass the appropriate bar chart config.

    
    <HighchartWrapper config={{
      chart: {
            type: "bar"
        }
      }}
      data={[]}
    >
    
    

    Edit

    import React from "react";
    import BarChart from "./BarChart";
    
    export default function App() {
      return (
        <div style={{ width: 400, height: 840 }}>
          <BarChart
            config={{
              chart: {
                height: 840,
                type: "bar"
              },
              xAxis: {
                categories: ["Positive", "Neutral", "Negative" ],
                title: {
                  text: null
                }
              },
              yAxis: {
                min: 0,
                title: {
                  text: "Population (millions)",
                  align: "high"
                },
                labels: {
                  overflow: "justify"
                }
              }
            }}
            data={[
              {
                name: "Series Name",
                data: [90, 9, 10]
              }
            ]}
          />
        </div>
      );
    }