In the above component of my React project I have used setInterval to create a State Array that has a maximum size of 10 and used ChartJS to represent the changes in that Array in a Line Graph, but multi[le values are being added into the Array at a time instead of just one.
I have tried adding the useEffect hook and clearInterval functionalities to help with the predictability of the setinterval function but it hasn’t worked. Thanks in advance for any help with the code .
import styles from "./LineGraph.module.css";
import { useEffect, useState, useRef } from "react";
import { Line } from "react-chartjs-2";
import {
Chart as ChartJS,
LineElement,
CategoryScale,
LinearScale,
PointElement,
} from "chart.js";
ChartJS.register(LineElement, CategoryScale, LinearScale, PointElement);
const Time = () => {
let now = new Date();
let hour = now.getHours();
let minute = now.getMinutes();
let second = now.getSeconds();
return `${hour}-${minute}-${second}`;
};
const LineGraph = (props) => {
const [dataSet, setDataset] = useState([0]);
const labels = useRef([0]);
const temperature=props.temperatureValue;
useEffect(() => {
console.log(props);
const temperature= props.Parameters.temperature;
console.log(props.Parameters.temperature);
const interval = setInterval(() => {
if (labels.current.length > 10) {
const newLabels = dataSet.slice(1, dataSet.length);
const newLabel = Math.floor(Math.random() * 1000);
labels.current.value = [...newLabels, newLabel];
} else {
labels.current = [...labels.current, Time()];
}
setDataset((dataSet) => {
if (dataSet.length > 10) {
const newDataSet = dataSet.slice(1, dataSet.length);
const newValue = Math.floor(Math.random() * 1000);
return [...newDataSet, newValue];
} else {
const newValue = Math.floor(Math.random() * 1000);
return [...dataSet, temperature];
}
});
return () => {
clearInterval(interval);
};
}, 10000);
}, [props]);
const data = {
labels: labels.current,
datasets: [
{
data: dataSet,
fill: true,
backgroundColor: "rgb(92, 158, 231)",
borderColor: "rgb(92, 158, 231)",
pointRadius: 5,
pointHoverRadius: 8,
pointBackgroundColor: "rgb(92, 158, 231)",
pointBorderColor: "rgb(92, 158, 231)",
pointHoverBackgroundColor: "rgb(92, 158, 231)",
pointHoverBorderColor: "rgb(92, 158, 231)",
borderWidth: 2,
tension: 0.5,
},
],
};
return (
<>
<Line data={data}></Line>
</>
);
};
export default LineGraph;
2
Answers
You have a problem with indentation. Here is your interval extracted. You can see that inside the
setInterval
you are returning a function to clear the interval.That doesn’t really do anything. You wanted to return that from the
useEffect
notsetInterval
.As you have it now, the cleanup is never called so it creates more and more intervals that run at the same time.
It seems like there are a couple of issues in your code. Let’s address them step by step:
Updating Dataset with Temperature:
It seems like you are using temperature instead of newValue when updating the dataset. If you want to use random values for demonstration purposes, you should replace temperature with newValue. Here’s the correction:
Or if you want to use the actual temperature data from props.temperatureValue, you can replace the line with:
Cleaning Up Interval:
Move the clearInterval outside the interval function, and ensure that the interval is cleared when the component unmounts. Your cleanup function should look like this: