Search code examples
javascriptreactjschart.jssetinterval

setnterval is acting unpredictably in React Project causing multiple changes to State Array


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;

Solution

  • It seems like there are a couple of issues in your code. Let's address them step by step:

    if (labels.current.length > 10) {
      const newLabels = labels.current.slice(1, labels.current.length);
      const newLabel = Time();
      labels.current = [...newLabels, newLabel];
    } else {
      labels.current = [...labels.current, Time()];
    }
    

    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:

    return [...dataSet, newValue];
    

    Or if you want to use the actual temperature data from props.temperatureValue, you can replace the line with:

    return [...dataSet, temperature];
    

    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:

    useEffect(() => {
      const interval = setInterval(() => {
        // ... (your existing code)
    
      }, 10000);
    
      return () => {
        clearInterval(interval);
      };
    }, [props]);