Reputation: 415
I am trying to build an employee org chart using Highcharts network graph but I'm running into errors. The idea is simple. I want to render an initial chart with the president and a few of their direct reports. After that, if the user clicks on a node in the chart, I want to pull data for that individual's direct reports and update the graph with the children nodes for that individual's subordinates. The back end API for the data pull is working fine
Here is my code:
import React, { useState, useEffect, useRef } from 'react';
import axios from 'axios';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import networkgraph from "highcharts/modules/networkgraph";
networkgraph(Highcharts);
const Employees3 = () => {
const chartComponent = useRef(null); // reference to chart obj
const [nodeData, setNodeData] = useState([
{ 'id': 'A', dataLabels: { enabled: true }, marker: { radius: 11, fillColor: 'red' } },
{ 'id': 'P', dataLabels: { enabled: true } },
{ 'id': 'K', dataLabels: { enabled: true } },
{ 'id': 'S', dataLabels: { enabled: true } },
{ 'id': 'D', dataLabels: { enabled: true } },
]);
const [linkData, setLinkData] = useState([
{ 'from': 'D', 'to': 'A' },
{ 'from': 'S', 'to': 'A' },
{ 'from': 'K', 'to': 'A' },
{ 'from': 'P', 'to': 'A' }
]);
const [chartOptions, setChartOptions] = useState({
chart: {
type: 'networkgraph',
plotBorderWidth: 1,
},
title: {
text: 'Phrasal verbs'
},
subtitle: {
text: 'Integration: ' + 'euler'
},
credits: false,
plotOptions: {
networkgraph: {
layoutAlgorithm: {
enableSimulation: false,
integration: 'euler',
linkLength: 25,
},
keys: ['from', 'to'],
marker: {
radius: 5,
lineWidth: 1
}
},
series: {
point: {
events: {
click: function () {
var name = this.id.replace(' ', '%20');
axios.get('api/employee_data/' + name)
.then(response => {
setNodeData(nodeData.concat(response.data.nodes));
setLinkData(linkData.concat(response.data.links));
chartComponent.current.chart.redraw();
}).catch( err => {
})
},
}
}
}
},
series: [{
allowPointSelect: true,
nodes: nodeData,
data: linkData,
}]
});
console.log('nodes: ', nodeData)
console.log('links: ', linkData)
return (
<div>
<HighchartsReact
highcharts={Highcharts}
options={chartOptions}
containerProps={{ style: { height: 700 } }}
allowChartUpdate = {true}
ref={chartComponent}
/>
</div>
)
};
export default Employees3;
I'm using a function on the series.event.click object to render a GET call to pull the child nodes and links from the server and update my state for nodeData and linkData. When I do a console log of these state arrays, it is showing me the right data. I then try to rerender the chart object with the updated data using the redraw method on the chart reference. The problem is that the chart is not rerendering with the new data using this approach. Instead it continues to show the old data.
Any thoughts on what I may be doing wrong here and how I can rerender the chart after the data update?
Much appreciated
EDIT (2-6-21)
axios.get('api/employee_data/' + name)
.then(response => {
setNodeData((prevState) => {
return [...prevState, ...response.data.nodes]
});
setLinkData((prevState) => {
return [...prevState, ...response.data.links]
});
setChartOptions({
series: [{
nodes: nodeData, //doesnt work
data: linkData //doesnt work
nodes: response.data.nodes, // works but doesn't give me what I need
data: response.data.links,
}]
});
});
Upvotes: 1
Views: 3454
Reputation: 39079
You need to update state which is directly related with a chart component options props:
plotOptions: {
...,
series: {
point: {
events: {
click: function () {
var name = this.id.replace(' ', '%20');
axios.get('api/employee_data/' + name)
.then(response => {
setChartOptions({
series: [{
nodes: response.data.nodes,
data: response.data.links
}]
});
}).catch( err => {})
}
}
}
}
}
Live demo: https://codesandbox.io/s/highcharts-react-demo-ngq7w?file=/demo.jsx
Upvotes: 1