Search code examples
reactjshighchartsreact-highcharts

Reformat parsing of json data into highcharts using Object method


I know just a little React but have been tasked with displaying json using highcharts. The json is returned via a fetch api call and looks like below. I currently use the code at bottom and it works fine. However, it is hard-coded and I would like to refactor/improve it, maybe looping over the keys object. Research shows I could potentially use .entries or .map, but examples I find call those functions in the render section, but with the way my code it, I need to do it in getConfig() and componentDidMount().

Suggestions?

JSON to be displayed using highcharts

[
    {
        "reason": "reason-1", 
        "fq_counts": {"FQ1": 35, "FQ4": 92, "FQ3": 91, "FQ2": 49}
    }, 
    {
        "reason": "reason-2", 
        "fq_counts": {"FQ1": 53, "FQ4": 32, "FQ3": 82, "FQ2": 16}
    }, 
    // etc...
]

Metrics.jsx

import HighCharts from "highcharts"
import HighchartsReact from "highcharts-react-official";
// other imports...

const getConfig = ( metricsData ) => ({
    chart: {
        type: 'column'
    },
    title: {
        text: 'my title'
    },
    
    // other highcharts objects...
    
    series: [
        {
            name: metricsData["reason0"],
            data: [
                metricsData["data0Label0"], 
                metricsData["data0Label1"], 
                metricsData["data0Label2"], 
                metricsData["data0Label3"], 
            ]
        },{
            name: metricsData["reason1"],
            data: [
                metricsData["data1Label0"], 
                metricsData["data1Label1"], 
                metricsData["data1Label2"], 
                metricsData["data1Label3"], 
            ]
        },
        // more objects...
    ]
});


class Metrics extends Component {

    constructor() {
      super();
      this.state = {
          metricsData: {},
        }
    }
    
    componentDidMount() {
        fetch(process.env.MY_ENDPOINT + '/metrics', {credentials: 'include'})
        .then(res => res.json())
        .then(data => {
            const keys = Object.keys(data[0].fq_counts);
            this.setState({
                metricsData: {
                
                    "reason0":data[0].reason,
                    "data0Label0":data[0].fq_counts[keys[0]],
                    "data0Label1":data[0].fq_counts[keys[1]],
                    "data0Label2":data[0].fq_counts[keys[2]],
                    "data0Label3":data[0].fq_counts[keys[3]],
                    
                    "reason1":data[1].reason,
                    "data1Label0":data[1].fq_counts[keys[0]],
                    "data1Label1":data[1].fq_counts[keys[1]],
                    "data1Label2":data[1].fq_counts[keys[2]],
                    "data1Label3":data[1].fq_counts[keys[3]],
                    
                    // more data...
                   
                }
            });
        });
    }  
  
    render() {
      const { metricsData } = this.state;
      const chartConfig = getConfig(metricsData);
        return (
            <Paper sx={{width: 1}}>
                <Box
                    sx={{
                    display: 'flex',
                    flexDirection: 'column',
                        alignItems: 'flex-start',
                    p: 1,
                    m: 1,
                    bgcolor: 'background.paper',
                    borderRadius: 1,
                    }}
                    <Typography variant="h4" gutterBottom>
                        <b>Quarterly Metrics</b>
                    </Typography>
                            <Divider />
                    <Typography variant="p" gutterBottom>Totals</Typography>
                    <HighchartsReact highcharts={HighCharts} options={chartConfig}/>
                </Box>
            </Paper>
        );
    }
}
export default Metrics;

Solution

  • You can relatively easily convert your data to the Highcharts series structure. The below concept will be the same for React and pure JS:

    const keys = Object.keys(responseData[0].fq_counts);
    const series = [];
    
    responseData.forEach((dataEl, index) => {
        series.push({ name: dataEl.reason, data: [] });
        keys.forEach(key => {
            series[index].data.push([key, dataEl.fq_counts[key]]);
        });
    });
    

    Live demo: http://jsfiddle.net/BlackLabel/deskutc4/

    API Reference: https://api.highcharts.com/highcharts/series.column.data