Highcharts not rendering : React+Typescript+Highcharts - reactjs

Trying to bring up a highchart using react. I am having multiple fetch api calls(for illustration, I have added only 2) whose data I will be using to render something in the UI.
In this example data1 is used to render a table, data2 is used to render a highchart.
I am storing the outputs of these calls in a state object. When I am calling these API's, I am getting the data but unable to set it to "series" property of highcharts for rendering, as a result nothing is getting rendered.
Structure of the data I am fetching
"api2" : [
{
"name" : "Test1",
"value" : 12
},
{
"name" : "Test2",
"value" : 9
}
]
Can someone help me with this? Where am I going wrong?
I am using highcharts-react-official for this
Code
import * as React from 'react';
import Highcharts from 'highcharts'
import HighchartsReact from 'highcharts-react-official';
interface IState {
data1: [];
data2: [];
}
interface IProps {}
class Example extends React.Component<IProps,IState> {
constructor(props:any)
{
super(props);
this.state = {
data1: [],
data2: []
}
}
componentDidMount()
{
Promise.all([
fetch('http://localhost:3001/api1'),
fetch('http://localhost:3001/api2')
])
.then(([res1, res2]) => Promise.all([res1.json(), res2.json()]))
.then(([data1, data2]) => this.setState({
data1: data1,
data2: data2
}));
}
render() {
let options:any;
options = {
chart: {
type: 'column'
},
credits: false,
exporting: {enabled: false},
title: {
text: ''
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'bottom'
},
xAxis: {
visible:false
},
yAxis: {
visible:false
},
plotOptions: {
column: {
dataLabels: {
enabled: true }
}
},
series: this.state.data2
};
return(
<div className="an-content">
//some table rendering will happen here
<HighchartsReact
highcharts={Highcharts}
options={options}
/>
</div>
)
}
}
export default Example;

You need to provide the data format required by Highcharts:
this.setState({
data2: data2.map(x => ({ name: x.name, data: [x.value] }))
});
Live demo: https://codesandbox.io/s/7w2pw4p900
API Reference: https://api.highcharts.com/highcharts/series.column.data

Related

Adding series to highchart and remove loading without creating new chart

I'm using Highchart with React.
For the moment I created a starting options:
/**
* Initial chart options, with "loading" enabled
*/
const chartOptions = {
accessibility: {
enabled: false
},
chart: {
type: "column",
events: {
load() {
const chart = this;
chart.showLoading(`${LOADING}...`);
}
}
}
};
In that component I call an API that returns some data to use. So, at that moment, I want to remove the "loading" and adding the data.
I solved for the moment with:
const [options, setOptions] = useState(chartOptions);
useEffect(() => {
if (detail) {
setOptions({
...chartOptions,
chart: {
type: "column"
},
xAxis: {
categories: detail.map(
(item) =>
`${item.data_em.substring(4, 6)}/${item.data_em.substring(0, 4)}`
)
},
series: [
{
name: "Alfa",
color: "#69BC66",
data: detail.map((item) => item.ricevuti)
},
{
name: "Beta",
color: "#DC3545",
data: detail.map((item) => item.mancanti)
},
]
});
}
}, [detail]);
<ChartComponent options={options} />
So, setting a new options in local State when data are ready. But I imagine that in this manner I get a different chart.
It works, but is there a better method?
With using the highcharts-react-official wrapper, the chart is recreated on state update only if immutable option is enabled. Otherwise, only chart.update method is called to apply changes.
Therefore, it is better to apply only the new options. In your case it will be:
useEffect(() => {
if (detail) {
setOptions({
chart: {
type: "column"
},
xAxis: {
categories: detail.map(
(item) =>
`${item.data_em.substring(4, 6)}/${item.data_em.substring(0, 4)}`
)
},
series: [{
name: "Alfa",
color: "#69BC66",
data: detail.map((item) => item.ricevuti)
},
{
name: "Beta",
color: "#DC3545",
data: detail.map((item) => item.mancanti)
},
]
});
}
}, [detail]);
Live demo: https://codesandbox.io/s/highcharts-react-demo-3lvomg?file=/demo.jsx
Docs: https://www.npmjs.com/package/highcharts-react-official#optimal-way-to-update

Objects are not valid as a React child error in React Datatable

OK, so Im getting this error when trying to return some data from my web api. Ive tried all as suggested on other similar posts but cant get this working. Any help appreciated.
Objects are not valid as a React child. If you meant to render a collection of children, use an array instead.
clg(records) returns this:
[{
id:1,
Listing: {id: 2, title: 'Testtt'},
ListingId: 2
},
{
id:2,
Listing: {id: 3, title: 'hell world'},
ListingId: 3
}]
here is my reactjs code:
class Products extends Component {
constructor(props) {
super(props);
this.columns = [
{
key: "id",
text: "Id",
className: "id",
align: "left",
sortable: true,
},
{
id:"ListingId"
text: "Merchant ID",
className: "name",
align: "left",
sortable: true,
},
}
];
this.state = {
records: []
};
this.getData = this.getData.bind(this);
}
componentDidMount() {
this.getData()
};
componentWillReceiveProps(nextProps) {
this.getData()
}
getData() {
axios
.get("/api/products")
.then(res => {
this.setState({ records: res.data})
})
.catch()
}
render() {
const {records}=this.state;
console.log(records);
return (
<div>
<ReactDatatable
records={this.state.records}
columns={this.columns}
loading='true'
/>
</div>
);
}}
Currently its displaying ListingId in the column, how can i display the Listing title instead?
i am currently using this package :
https://www.npmjs.com/package/#ashvin27/react-datatable
Here is the solution to my question
{
key:'ListingId',
text: "Column Title",
className: "name",
align: "left",
sortable: true,
cell: record => {
console.log(record)
return (
<span>{record.Listing.title}</span>)
}
},

React js and chart js pie chart type

Hello everyone i need to get a dynamic chart js pie type ,
this is the request to get the data :
async componentDidMount(){
axios.get("http://localhost:8080/requete/tab1")
.then(response => response.data)
.then((data) =>{
this.setState({dataL : data})
})
}
this the code with static data :
const options = {
animationEnabled: true,
exportEnabled: true,
theme: "light1",
title:{
text: "Trip Expenses"
},
data: [{
type: "pie",
indexLabel: "{label}: {y}%",
startAngle: -90,
dataPoints: [
{ y: 5, label: "Lost" },
{ y: 24, label: "Won" },
]
}]
}
please what i should to do to get the dynamic value at my chart
Try using react-apexcharts. this lets you create dynamic charts as your wish
You should make new component with chart.js pie and define props, too.
After receiving data from backend, you would import this component and send this data as props.
<Pie {...this.state.data} />
props: {
data: Array,
....
}
computed() {
pie() {
return this.data || [];
}
}

(Lifecycle problem?) React Chart js-2 not updating data from componentDidMount

I am trying to populate chart data from my backend.
Although I am fetching data and pushing data in componentDidMount, the Bars or Scatters are not loaded on page load.
If I change my screen width in inspect mode in google dev tools, it starts loading which leads me to believe this is a lifecyle problem.
However, changing it to componentWillMount did not change anything. Putting a if statement before render like below just stops loading the chart altogether.
if(this.state.data.datasets[0].data.length ===0){
return null;
}
Any way to fix this problem?
import React, { Component } from "react";
import axios from "axios";
import { Bar, Scatter } from "react-chartjs-2";
export class Data extends Component {
constructor(props) {
super(props);
this.state = {
provider: [],
data: {
labels: ["Action", "Anime", "Children"],
datasets: [
{
label: "Total",
backgroundColor: "rgba(255, 159, 64, 0.4)",
borderColor: "white",
borderWidth: 1,
stack: 1,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: []
},
{
label: "Above ⭐️8.5",
backgroundColor: "white",
type: "scatter",
showLine: false,
stack: 1,
data: []
}
]
}
};
}
componentDidMount() {
axios.get("http://localhost:8001/provider").then(res =>
this.setState({ provider: res.data }, () => {
this.pushAction();
})
);
}
pushAction() {
const dataState = this.state.data;
const oldDataTotal = this.state.data.datasets[0].data;
const oldDataGood = this.state.data.datasets[1].data;
oldDataTotal.push(this.state.provider[0].huluAction);
oldDataTotal.push(this.state.provider[0].huluAnime);
oldDataTotal.push(this.state.provider[0].huluChildren);
oldDataGood.push(this.state.provider[0].Action);
oldDataGood.push(this.state.provider[0].Anime);
oldDataGood.push(this.state.provider[0].Children);
}
render() {
console.log(this.state.musicalData);
const options = {
responsive: true,
maintainAspectRatio: false,
legend: {
display: true
},
type: "bar",
scales: {
xAxes: [
{
stacked: true
}
],
yAxes: [
{
stacked: true
}
]
}
};
return (
<div>
<Bar data={this.state.data} height={300} options={options} />
</div>
);
}
}
export default Data;
you have to update the state after changing the datasets,
pushAction = () => {
const dataState = this.state.data;
const oldDataTotal = this.state.data.datasets[0].data;
const oldDataGood = this.state.data.datasets[1].data;
oldDataTotal.push(this.state.provider[0].huluAction);
oldDataTotal.push(this.state.provider[0].huluAnime);
oldDataTotal.push(this.state.provider[0].huluChildren);
oldDataGood.push(this.state.provider[0].Action);
oldDataGood.push(this.state.provider[0].Anime);
oldDataGood.push(this.state.provider[0].Children);
this.setState({data: {...dataState, datasets : [...oldDataTotal, oldDataGood]}});
}

How can I display the current value from a chart?

I am new to React and I work on a small project basically, I have a chart and I just want to display the current value from the chart.
For example, I have a chart with 4 random values:[5,2,5,1], so I want to have displayed the current value below the chart like first is 5, second is 2 and so on.
Here is my part of code:
class App extends React.Component {
addPoint = (point) => {
currentData = this.state.options.series[0].data
this.setState({
options: {
series: [
{ data: [...currentData, point]}
]
}
});
}
constructor(props) {
super(props);
this.internalChart = undefined;
this.dataStream = new DataStream();
this.dataStream.setUpdateCallback(this.addPoint);
this.state = {
options: {
chart: {
events: {
load: function () {
}
}
},
time: {
useUTC: false
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 2
},
title: {
text: 'Live random data'
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: [[(new Date()).getTime(), 0]]
}]
}
};
}
render() {
return (
<HighchartsReact
constructorType={"stockChart"}
highcharts={Highcharts}
options={this.state.options}
/>
);
}}
Based on your snippet code, try to make random method by using function
Math.floor(Math.random() * Math.floor(max))
And then assign the options to HighchartsReact,
Full code on sandbox: https://codesandbox.io/s/headless-dream-0lzj1

Resources