I am trying to generate a scatterplot using chartJS. The plot wont graph.
When i feed in data manually by declaring the data, it works fine,
var scatter = [
{ x: 65, y: 75 },
{ x: 59, y: 49 },
{ x: 80, y: 90 },
{ x: 81, y: 29 },
{ x: 56, y: 36 },
{ x: 55, y: 25 },
{ x: 40, y: 18 },
]
but when I get the data via an API call and push the data to the array, it won't work. Any suggestions? I suspect its to do with how data is pushed onto the array but not sure what's wrong.
Thank you
Minimum solution below
import React, { useEffect, useState } from 'react';
import axios from 'axios';
function App() {
const [scatterData, setScatterData] = useState({});
const chart = () => {
var scatter = [];
axios.get('http://dummy.restapiexample.com/api/v1/employees')
.then(res => {
let temp = res.data.data
temp.forEach( i=> {
let age = parseInt(i.employee_age)
let salary = parseInt(i.employee_salary)
scatter.push({"x": age,
"y": salary})
})
}).catch(err => {
console.log(err)
})
console.log(scatter)
setScatterData({
datasets: [
{
label: 'test',
fill: true,
backgroundColor: 'rgba(75,192,192,0.4)',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 10,
pointHoverBackgroundColor: 'rgba(75,192,192,1)',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 3,
pointHitRadius: 10,
data: scatter,
backgroundColor: [
'rgba(75,192,192,0.6)'
],
borderWidth: 4
}
]
});
}
useEffect(() ={
chart()
},[])
return (
<div className ="container-fluid">
<div class="row">
<div className ="col-md-12">
<Scatter data={scatterData}/>
</div>
</div>
</div>
)
};
Try calling the update method on your chart object/instance after you pushed all the data from the api to your scatter array
Related
I have a radar chart in which "100" represents the global average value for a characteristic.
To make the chart more readable I want to make only the grid line that indicates the 100 value mark dashed.
Is there a way to do this?
Current chart code is here: jsfiddle.
const config = {
type: 'radar',
data: data,
options: {
elements: {
line: {
borderWidth: 3
},
point: {
pointRadius: 5
}
},
scales: {
r: {
angleLines: {
lineWidth: 2
},
grid: {
circular: true,
lineWidth: 2
}
}
}
}
};
In my opinion, the logically correct answer is to define grid.borderDash as follows:
grid: {
...
borderDash: ctx => ctx.tick.value == 100 ? [8, 4] : []
},
To make it work however, I had to use ctx.tick.value == 95 (This could be a bug in Chart.js). Please take a look at your amended code and see how it works.
let dataValues = [100, 120, 80, 100, 90, 110, 100, 100, 100]
const sum = dataValues.reduce((a, b) => a + b, 0);
const avg = sum / dataValues.length;
const sorted = [...dataValues].sort(function(a, b) {
return a - b;
});
const data = {
labels: dataValues.map((v, i) => 'Signal ' + (i + 1)),
datasets: [{
label: '9 signals',
data: dataValues,
fill: true,
backgroundColor: 'rgba(210, 203, 203, 0.4)',
borderColor: 'rgb(210, 203, 203, 0.6)',
pointBackgroundColor: function(context) {
var index = context.dataIndex;
var value = context.dataset.data[index];
return value < sorted[3] ? 'blue' :
value < sorted[5] ? 'green' :
value < sorted[7] ? 'orange' :
'red';
},
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgb(255, 99, 132)'
}
]
};
const config = {
type: 'radar',
data: data,
options: {
elements: {
line: {
borderWidth: 3
},
point: {
pointRadius: 5
}
},
scales: {
r: {
suggestedMin: 70,
angleLines: {
lineWidth: 2
},
grid: {
circular: true,
lineWidth: 2,
borderDash: ctx => ctx.tick.value == 95 ? [8, 4] : []
},
ticks: {
stepSize: 5
}
}
}
}
};
let myChart = new Chart('myChart',
config
);
.chartBox {
width: 400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
<div class="chartBox">
<canvas id="myChart"></canvas>
</div>
I currently have a dynamic graph that updates with the redux state in my react application, but after updating React to 18.0 I have run into a issue with react-chartjs-2 that is telling me I need to destroy the canvas before rendering a new chart.
I found some sources on other posts and blogs but they were all aimed at class components for the graph, and I am using a functional component. Is the only solution to this problem to render it as a class component or can it be rendered with a functional component?
Here is my component:
import { Typography } from "#mui/material";
import { Line } from "react-chartjs-2";
import { useSelector } from "react-redux";
import { selectSensorGraph } from "../../redux/slices/robotSlice";
const data = [
50, 65, 85, 65, 45, 25, 0, -15, -25, -10, 35, 65, 85, 65, 45, 25, 0, -15, -5,
-10,
];
const borderColours = data.map((value) =>
value < 0.1 ? "rgb(0, 157, 255)" : "rgb(255, 0, 0)"
);
function SensorGraph() {
const graph_data = useSelector(selectSensorGraph);
try {
var label_list = [];
var data_list = [];
graph_data["data"].forEach((row) => {
var date = new Date(row["Timestamp"] * 1000);
var hours = date.getHours();
var minutes = (date.getMinutes() < 10 ? "0" : "") + date.getMinutes();
label_list.push(`${hours}:${minutes}`);
data_list.push(row[graph_data["sensor"]]["value"]);
});
} catch (err) {
console.log(`Error: ${err}`);
}
const graphHeader = () => {
if (graph_data["sensor"].includes("Speed")) {
return "Speed in RPM";
} else if (graph_data["sensor"].includes("Temp")) {
return "Temperature in °C";
} else if (graph_data["sensor"].includes("Torque")) {
return "Torque in N*m";
}
};
const chartData = {
labels: label_list,
datasets: [
{
label: graphHeader(),
data: data_list,
borderWidth: 5,
// borderColor: borderColours,
fill: {
target: "origin",
above: "rgb(255, 0, 0, 0.5)",
below: "rgb(0, 157, 255, 0.5)",
},
pointBorderWidth: 2,
pointBackgroundColor: borderColours,
},
],
};
const options = {
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
max: 100,
min: -100,
},
},
],
},
animation: {
duration: 0,
},
};
return (
<>
{data_list.length >= 1 ? (
<Line data={chartData} options={options} />
) : (
<Typography>No sensor data</Typography>
)}
</>
);
}
export default SensorGraph;
I'm new and practicing react.js.
I'm trying to update the content of array with useState by clicking a send-button, but it doesn't work as I expect.
Below is problem I'm having. Idk to add date and number in a row.
enter image description here
also, below is what I expect.
enter image description here
code:
import React, { useState, useRef } from 'react';
import classes from '../style/LineChart.module.css'
import { Button, Input } from '#chakra-ui/react';
import { Line } from 'react-chartjs-2'
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
} from "chart.js";
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title,
Tooltip, Legend);
const LineChart = () => {
const [numData, setNumData] = useState([0]);
const [date, SetDate] = useState(['']);
const calVal = useRef(null);
const chooseDate = useRef(null);
const onClick = () => {
setNumData([calVal.current.value]);
calVal.current.value = '';
SetDate([chooseDate.current.value]);
// SetDate([...date, chooseDate.current.value])
chooseDate.current.value = '';
}
const data = {
labels: [date],
datasets: [
{
label: 'How many todos can you achieve?',
fill: true,
lineTension: 0.1,
backgroundColor: 'rgba(75,192,192,0.4)',
borderColor: 'rgba(75,192,192,1)',
borderCapStyle: 'round',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'square',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#eee',
pointBorderWidth: 10,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgba(75,192,192,1)',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 1,
pointRadius: 1,
pointHitRadius: 10,
data: [numData]
}
]
};
const checkOfDelete = () => {
let result = window.confirm('Reset. ok?')
if(result) {
console.log('Delete.');
} else {
alert('fail.')
}
};
return (
<div mt='2'>
<Line data={data}/>
<Input className={classes.input} ref={chooseDate} variant='outline' w='40%' ml='30%' mb='3' mt='3' borderRadius='15px' type='text' label='date' placeholder='Date'/>
<Input className={classes.input} ref={calVal} variant='outline' w='54%' ml='23%' mb='3' borderRadius='15px' type='number' label='number' placeholder='How many?'/>
<br/>
{data.labels.length < 8 ? <Button colorScheme='teal' ml='21%' mr='2' onClick={onClick}>Send</Button> : <p>date is full.</p>}
<Button colorScheme='teal' onClick={checkOfDelete} >Reset</Button>
</div>
)
};
export default LineChart;
To work well, I've tried this way.
const data = {
labels: [calVal.current.value ,...date],
datasets: [
{
label: 'How many todos can you achieve?',
fill: true,
lineTension: 0.1,
backgroundColor: 'rgba(75,192,192,0.4)',
borderColor: 'rgba(75,192,192,1)',
borderCapStyle: 'round',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'square',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#eee',
pointBorderWidth: 10,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgba(75,192,192,1)',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 1,
pointRadius: 1,
pointHitRadius: 10,
data: [chooseDate.current.value,...numData]
}
]
};
but if this, I got error like: "Uncaught TypeError: Cannot read properties of null (reading 'value')"
Can someone please help me? I am sorry if it is very basic but I am only starting out..
You are defining the values as null. You only update the values in the onClick function.
const calVal = useRef(null);
const chooseDate = useRef(null);
add below the above code
calVal.current.value = ''
chooseDate.current.value = ''
useEffect(() => {
let ctx = document.getElementById("LineChart");
const blue = [2000, 2100, 2400, 2450, 3000];
const yellow = [1800, 2150, 2550, 2800, 2000];
const pink = [1200, 1100, 1050, 1010, 1000];
const LineChart = new Chart(ctx, {
type: "line",
data: {
labels: ["Jan", "Feb", "Mar", "Apr", "May"],
datasets: [
{
data: blue,
label: "New MRR",
fill: false,
lineTension: 0.5,
backgroundColor: "#3ea5e0",
borderColor: "#3ea5e0",
pointBorderWidth: 1,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointRadius: 1,
pointHitRadius: 10,
},
{
data: yellow,
label: "Net New MRR",
fill: false,
lineTension: 0.5,
backgroundColor: "#ad9a52",
borderColor: "#ad9a52",
pointBorderWidth: 1,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointRadius: 1,
pointHitRadius: 10,
},
{
data: pink,
label: "Lost MRR",
fill: false,
lineTension: 0.5,
backgroundColor: "#5c3784",
borderColor: "#5c3784",
pointBorderWidth: 1,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointRadius: 1,
pointHitRadius: 10,
},
],
},
options: {
scales: {
yAxes: [
{
ticks: {
beginAtZero: false,
callback: function (value, index, values) {
return "$" + value;
},
},
},
],
},
},
});
let ctx2 = document.getElementById("BarChart");
const BarChart = new Chart(ctx2, {
type: "bar",
data: data,
});
I want to create a common chart component with same x-axis values but different y-axis values.I have switch case according to their type.So I can render charts with their types.Is there a short way to create a common chart or do I have to code all of them? Because right now I can only render one line chart.
Here is how you can create a common Chart component which will draw the chart given a custom data.
https://codesandbox.io/s/serverless-frog-6bu2f?file=/src/App.js
I am having tough time understanding how I could create Graphs in React (this is first time I am working on it)
Can someone help me by sharing which library are you using and how would you use it to plot 3 data set which looks something like this in a single graph
This would be how my data set look.
(3) [{…}, {…}, {…}]
0:{id: "SAMPLE_#SPMJXVC_1_2", x: Array(963), y: Array(963)}
1: {id: "SAMPLE_#SPMJXVC_1_3", x: Array(964), y: Array(964)}
2: {id: "SAMPLE_#SPMJXVC_1_1", x: Array(954), y: Array(954)}
Chart.js is a very popular library for creating Javascript charts.
There is a wrapper that makes Chart.js easy to use in React: https://github.com/jerairrest/react-chartjs-2
If you don't want to use that, you can read this article for more ideas:
https://www.overloop.io/blog/2018/6/19/top-5-react-chart-libraries
If you decide to use this react-chartjs-2 package then in React you'd install the package and then follow the instructions in their github. For a scatter plot you have to setup the data object and then simply render <Scatter data={data} />
Here is their full example I took from their site:
import React from 'react';
import {Scatter} from 'react-chartjs-2';
const data = {
labels: ['Scatter'],
datasets: [
{
label: 'My First dataset',
fill: false,
backgroundColor: 'rgba(75,192,192,0.4)',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgba(75,192,192,1)',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: [
{ x: 65, y: 75 },
{ x: 59, y: 49 },
{ x: 80, y: 90 },
{ x: 81, y: 29 },
{ x: 56, y: 36 },
{ x: 55, y: 25 },
{ x: 40, y: 18 },
]
}
]
};
export default React.createClass({
displayName: 'ScatterExample',
render() {
return (
<div>
<h2>Scatter Example</h2>
<Scatter data={data} />
</div>
);
}
});