1

I want to make an algorithm that every time you log into the page to start a 5 minute counter and while this 5 minute counter is going in I want to make some actions every minute for example.

I tried starting a setTimeout with useEffect and also setting a flag value to know when the 5 minutes are over:

const [initialTime, setInitialTime] = useState(true)
  useEffect(() => {
    console.log('starting counter');
    setTimeout(() => {
      setInitialTime(false)
      console.log('changing the time' + " - " + initialTime);
    }, 5000);
    
  }, [])
  

and under it I added the setInterval function which I want to go off only whenever the flag above (initialTime is true) otherwise not.

 useEffect(() => {
    setInterval(() => {
      if (initialTime) {
        //some action
      }
    }, 1000);
  }, [])

In my head that should work, but setInterval reacts really strange, it doesn't detect the state changes, this is an example log if I place the setTimeout to 5 seconds and setInterval to 1 second:

true
true
true
true
changing the time - true
true

and then it continues, the setTimeout doesn't even change the state in this case, but even if it does, setInterval doesn't detect it and it still goes through. I need help completing the algorithm.

Chrissisbeast
  • 151
  • 1
  • 8
  • Does this answer your question? [react hooks and setInterval](https://stackoverflow.com/questions/53981593/react-hooks-and-setinterval) – spender Jul 30 '21 at 13:53
  • If you want to understand what's going on in-depth, here's a good article with a well written hook to get you out of trouble: https://overreacted.io/making-setinterval-declarative-with-react-hooks/ – spender Jul 30 '21 at 13:54

1 Answers1

1

Using setInterval inside a `useEffect is a known issue with React Hooks. Dan Abramov wrote a useful blog post explaining how to resolve it. https://overreacted.io/making-setinterval-declarative-with-react-hooks/

The key is to replace

useEffect(() => {
    setInterval(() => {
      if (initialTime) {
        //some action
      }
    }, 1000);
  }, [])

with this:

function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}
dmc85
  • 250
  • 1
  • 9