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

Advertisements

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 :

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.

const interval = setInterval(() => {
  return () => {
    clearInterval(interval);
  };
}, 10000);

That doesn’t really do anything. You wanted to return that from the useEffect not setInterval.

const interval = setInterval(() => {
}, 10000);
return () => {
  clearInterval(interval);
};

As you have it now, the cleanup is never called so it creates more and more intervals that run at the same time.

Leave a ReplyCancel reply