using react ionic 6 with chartJS - reactjs

I'm trying to render a graph with ionic react but i keep getting errors such as:
Uncaught Error: Canvas is already in use. Chart with ID '0' must be
destroyed before the canvas with ID '' can be reused.
import { Bar } from "react-chartjs-2";
const Graph: React.FC = (props) => {
const data = {
labels: ["Billable", "Non Billable"],
datasets: [
{
label: "Billable Vs. Non Billable",
backgroundColor: ["#36a2eb", "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],
},
],
};
return (
<div>
<h2>bar example</h2>
<Bar
data={data}
width={100}
height={50}
options={{ maintainAspectRatio: false }}
/>
</div>
);
};
export default Graph;
does anyone knows how to solve it?

I have found a solution, credit to #TechMaze from this post.
I had to import CategoryScale from chart.js and Chart from chart.js/auto.
it seems that Chart from chart.js wont solve this issue(!)
import { Bar } from "react-chartjs-2";
import { CategoryScale } from "chart.js";
import { Chart as ChartJS } from "chart.js/auto";
import {
IonTitle,
useIonViewWillEnter,
useIonViewWillLeave,
} from "#ionic/react";
const Graph: React.FC = () => {
useIonViewWillEnter(() => {
ChartJS.register(CategoryScale);
}, []);
useIonViewWillLeave(() => {
ChartJS.unregister(CategoryScale);
}, []);
const data = {
labels: ["Billable", "Non Billable"],
datasets: [
{
label: "Billable Vs. Non Billable",
backgroundColor: ["#36a2eb", "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],
},
],
};
return (
<>
<IonTitle>Bar Example</IonTitle>
<Bar data={data} />
</>
);
};
export default Graph;

Related

React react-chartjs-2 adding x and y axis labels to a line graph

import React from "react";
import { Line } from "react-chartjs-2";
// "chart.js": "^2.9.4",
// "react-chartjs-2": "^2.11.1"
const ext_data = [11, 19, 3, 5, 2, 3, 14, 19];
const ll = Array.from(Array(ext_data.length).keys());
const data = {
labels: ll,
datasets: [
{
label: "Profit$",
data: ext_data,
fill: false,
backgroundColor: "rgb(255, 99, 132)",
borderColor: "rgba(255, 99, 132, 0.4)"
}
]
};
const options = {
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
};
const LineChart = () => (
<>
<div className="header">
<h1 className="title">Profit Trend</h1>
<div className="links"></div>
</div>
<Line data={data} options={options} />
</>
);
export default LineChart;
I am trying to add x-axis name : "time" and y-axis name: "number of cars".
I went into the documentation : https://www.chartjs.org/docs/latest/axes/labelling.html
However, I was not able to find something that was useful.
Thank you for your time.
In react-chartjs-2, to add your title to your axis, just add this to your yAxes array of options (options.scales.yAxes[]):
scaleLabel: {
display: true,
labelString: "number of cars",
fontColor: "color you want",
}
same for your xAxes.

I want to change the position and style of the label in the React chart

I am using react-chartjs-2. I want to display the position of the label below the graph. Also, the shape of the label is currently square, but I would like to change it to a round shape. I specified option and position: bottom, but the position of the label did not change.
import "./styles.css";
import React from "react";
import { Bar } from "react-chartjs-2";
const data = [
{
label: "a",
data: [56, 23, 55, 56, 57]
},
{
label: "b",
data: [22, 17, 32, 47, 62]
},
{
label: "c",
data: [46, 73, 25, 76, 27]
}
];
const App = () => {
const CHART_COLORS = ["#e35b2c", "#e77235", "#eb8a40"];
const list = data.map((d, index) => {
return {
label: d.label,
backgroundColor: CHART_COLORS[index],
data: d.data,
stack: 1
};
});
const options = {
legend: {
position: "bottom"
}
};
return (
<>
<div className="App">
<Bar
data={{
labels: ["block1", "block2", "block3"],
datasets: list
}}
width={100}
height={50}
options={options}
/>
</div>
</>
);
};
export default App;
Legend option is changed in latest version of chartjs to,
Namespace: options.plugins.legend
plugins: {
legend: {
position: "bottom",
labels: {
usePointStyle: true //for style circle
}
}
}
};
You can check working demo here, https://codesandbox.io/s/react-chartjs-legend-option-prbgb
Reference : https://www.chartjs.org/docs/latest/configuration/legend.html

How to show data value on top of bar in react-chartjs-2?

I made bar chart in react-chartjs-2. I want to show data value of each bar on the top of the bar. For that I used the plugin calls chartjs-plugin-datalabels But it's not showing anything.
is it possible to show each value of bar chart ?
I want to show data value somethings like this.
Here is my code.
import React, { Component } from "react";
import "chartjs-plugin-datalabels";
import { Bar } from "react-chartjs-2";
export default class Button extends Component {
render() {
const dataBar = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
backgroundColor: "#EC932F",
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]
}
]
};
const options = {
plugins: {
datalabels: {
display: true,
color: "black"
}
},
legend: {
display: false
}
};
return (
<div>
<Bar data={dataBar} options={options} width={100} height={50} />
</div>
);
}
}
Any help would be appreciated.
import React, { Component } from "react";
import Chart from "chart.js/auto";
import ChartDataLabels from "chartjs-plugin-datalabels";
import { Bar } from "react-chartjs-2";
export default class Button extends Component {
componentDidMount() {
Chart.register(ChartDataLabels);
}
render() {
const dataBar = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
backgroundColor: "#EC932F",
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]
}
]
};
const options = {
plugins: {
datalabels: {
display: true,
color: "black",
formatter: Math.round,
anchor: "end",
offset: -20,
align: "start"
}
},
legend: {
display: false
}
};
return (
<div>
<Bar data={dataBar} options={options} width={100} height={50} />
</div>
);
}
}
Here you can see in componentDidMount we have registered chart data label plugin for displaying data.
And another thing is in the options added few more parameters as per below field
anchor: "end",
offset: -20,
align: "start"
This is used for displaying data in the top.
The react-chartjs-2 package holds a plugin property which can be set on the components.
Change the import from:
import "chartjs-plugin-datalabels";
to:
import ChartDataLabels from 'chartjs-plugin-datalabels';
On your component, add the plugin variable which holds the imported value.
from:
<Line data={data} options={options} />
to:
<Line data={data} plugins={[ChartDataLabels]} options={options} />
See this original stackoverflow answer to the similar question
use this "chartjs-plugin-datalabels": "^0.5.0" version
it works for me
Here is working example
https://codesandbox.io/s/barchart-knycb
const options2 = {
plugins: {
datalabels: {
anchor: "end",
align: "start",
formatter:(value,context)=>{
const datasetArray = []
context.chart.data.datasets.forEach((dataset)=>{
if(dataset.data[context.dataIndex] != undefined){
datasetArray.push(dataset.data[context.dataIndex])
}
})
function totalSum(total, datapoint){
return total + datapoint;
}
let sum = datasetArray.reduce(totalSum,0)
if(context.datasetIndex == datasetArray.length-1)
return sum
else
return ''
},
},
title: {
display: true,
text: 'Chart.js Bar Chart - Stacked',
},
},
responsive: true,
scales: {
x: {
stacked: true,
ticks: {
maxRotation: 70,
minRotation: 70
}
},
y: {
stacked: true,
},
},
};
const data1 = {
labels,
datasets: [
{
label: 'Dataset One',
data: [1,2,3,4,5,6,7],
backgroundColor: 'rgba(255, 99, 132, 0.5)',
},
{
label: 'Dataset Two',
data: [1,8,3,4,9,6,7],
backgroundColor: 'rgba(53, 162, 235, 0.5)',
},
],
};

Create a prop for a chart.js pie chart

I'm using Chart.js inside my react project.
and i want to structure my project as neatly as possible by creating components
and calling them on my App.js
How can I go about creating a react prop and calling it from another component without Actually calling my pie chart from the App.js
import React from 'react';
import {Pie} from 'react-chartjs-2';
const state = {
labels: ['January', 'February', 'March',
'April', 'May'],
datasets: [
{
label: 'Rainfall',
backgroundColor: [
'#B21F00',
'#C9DE00',
'#2FDE00',
'#00A6B4',
'#6800B4'
],
hoverBackgroundColor: [
'#501800',
'#4B5000',
'#175000',
'#003350',
'#35014F'
],
data: [65, 59, 80, 81, 56]
}
]
}
export default class App extends React.Component {
render() {
return (
<div>
<Pie
data={state}
options={{
title:{
display:true,
text:'Average Rainfall per month',
fontSize:20
},
legend:{
display:true,
position:'left',
}
}}
/>
</div>
);
}
}
If you create a component named PieChart in the PieChart.js file like this:
import React from 'react';
import { Pie } from 'react-chartjs-2';
export default class PieChart extends React.Component {
render() {
return (
<div>
<Pie
data={this.props.data}
options={{
title: {
display: true,
text: 'Average Rainfall per month',
fontSize: 20
},
legend: {
display: true,
position: 'left',
}
}}
/>
</div>
);
}
}
Then you can import it from the App.js in this way:
import React from 'react';
import PieChart from './PieChart';
const state = {
labels: ['January', 'February', 'March',
'April', 'May'],
datasets: [
{
label: 'Rainfall',
backgroundColor: [
'#B21F00',
'#C9DE00',
'#2FDE00',
'#00A6B4',
'#6800B4'
],
hoverBackgroundColor: [
'#501800',
'#4B5000',
'#175000',
'#003350',
'#35014F'
],
data: [65, 59, 80, 81, 56]
}
]
}
export default class App extends React.Component {
render() {
return (
<PieChart data={state} />
)
}
}
Here I've created a custom props named data and passed it to the PieChart component which is being accessed by this.props.data in the PieChart component. You can create multiple props as you want. Like you can pass options as well in this way.
Also you can keep your data(which is passed from the App as data props) in the PieChart component and call it from anywhere you want by <PieChart />.
Note: I've kept App.js and PieChart.js both files in the same directory.
This how I used piechart in my project:
in another file, you can create a custom component and add your code like below
export const StatusChart = ({ data }) => {
const [pieData, setPieData] = useState({});
useEffect(() => {
setPieData({
labels: ['declined', 'accepted', 'goterror', 'inprogress'],
datasets: [
{
data: [data.inprogress, data.got_error, data.accepted, data.declined],
backgroundColor: ['#F7464A', '#46BFBD', '#FDB45C', '#949FB1', '#4D5360'],
hoverBackgroundColor: ['#FF5A5E', '#5AD3D1', '#FFC870', '#A8B3C5', '#616774'],
},
],
});
}, [data]);
return (
<MDBContainer>
<Pie data={pieData} options={{ responsive: true }} />
</MDBContainer>
);
};
and in App.js you can use useState to save data like below:
const [generalData, setGeneralData] = useState(null);
and use it in your code:
{generalData ? <StatusChart data={generalData.status_chart} /> : <Spinner animation="border" />}

(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]}});
}

Resources