ChrisAMK
ChrisAMK

Reputation: 33

Issue with setting State with setInterval and clearInterval

I've found unexpected behaviour from react when trying to update state from an function being called at intervals by setInterval(). The aim is to have a Button that invokes a setInterval that calls a function that requests data from my MySQL database, then sets the first array of results to my State. I want that same button to also clear the interval when pressed again. On and on.

I've Noticed that the Code works fine if you comment out the setData function. I was hoping someone could explain why the code works as expected until you try setting state with the setInterval Function.

I'm guessing it's got something to do with the react state not updating straight away or maybe even it's got something to do with aysnc? Hopefully someone has a better understanding of what's going on.

currently the code is never getting to the else block, and just setting another interval that calls the getData function.

This code is not inside of a UseEffect Hook, The button has a OnClick={toggleLive}. This button is inside the Return()

const [data, setData] = useState({});

const getData = async () => {
     const lastEntry = await API.getLastEntry("rig08");
     console.log(lastEntry);
     setData(lastEntry[0] || 0);
  }

var dataUpdate = null;
const toggleLive = async () => {
   console.log(dataUpdate);
   if (!dataUpdate) {
      console.log("Condition");
      dataUpdate = setInterval(getData, 1000);
   } else {
      console.log("Else");
      clearInterval(dataUpdate);
      dataUpdate = null;
   }
}
return (
   <Button onClick={toggleLive} className={liveBtn}>Live</Button>
)

This is all relevant code, I can provide more if needed.

Upvotes: 1

Views: 105

Answers (2)

ChrisAMK
ChrisAMK

Reputation: 33

Just to conclude for anyone that may see this later,

The issue was that I was not correctly saving the interval. I Used Gerrod's answer with useRef and it worked a treat. Cheers everyone.

Upvotes: 0

gerrod
gerrod

Reputation: 6627

It's hard to tell without seeing the rest of your code, but I think what's happening is that you're not correctly saving the interval. Calling setData will make the component rerender, and each time the component rerenders, dataUpdate will get set to null:

var dataUpdate = null;

One way to handle this would be to save the dataUpdate interval as a ref -

const dataUpdateRef = React.useRef(null);
const toggleLive = async () => {
  console.log(dataUpdate);
  if (!dataUpdateRef.current) {
    console.log("Condition");
    dataUpdateRef.current = setInterval(getData, 1000);
  } else {
    console.log("Else");
    clearInterval(dataUpdateRef.current);
    dataUpdateRef.current = null;
  }
}

Upvotes: 1

Related Questions