0

I have this code to have a countdown on my site, going from 5 to 0 seconds:

const {useState, useCallback, useEffect} = React;
const Counter = ({isPlaying}) => {
  const [seconds, setSeconds] = useState(5);
  const [paused, setPaused] = useState(false);

  const toggle = useCallback(() => {
    setPaused(!paused);
  }, [paused, setPaused]);

  useEffect(() => {
    const interval = setInterval(() => {
      if (isPlaying && seconds > 0 && !paused) {
        setSeconds(seconds => seconds - 1);
        console.log('bla');
      }
    }, 1000);
    return () => clearInterval(interval);
  }, [seconds, isPlaying, paused]);

  return (
    <span className="count-down" id="count-down" onClick={toggle}>
        <span>00</span>
        <span>:</span>
        <span>0<span id="sec-count">{seconds}</span></span>
    </span>
  );
}

ReactDOM.render(<Counter isPlaying={true}/>, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

in a functional component.

in Chrome and Firefox this works as expected. It counts down from 5 to 0, and you see the 'bla' in the console 5 times. But in Safari it doesn't re-render. It counts down only once or twice, so showing 3 or 4, after that it stops re-rendering. But the console still shows 'bla' 5 times.

Any idea why in Safari it stops re-rendering, even though the interval clearly still runs?

Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
Danny Hobo
  • 574
  • 1
  • 5
  • 24
  • What is `isPlaying` ? – Nick Parsons Aug 28 '20 at 14:07
  • another boolean that comes in from props. it's always true - it's old code that needs some cleanup. – Danny Hobo Aug 28 '20 at 14:10
  • Ah ok, I made you a runnable code snippet so people can (hopefully) see the issue you're mentioning – Nick Parsons Aug 28 '20 at 14:12
  • 1
    FYI: setTimeout is not accurate – epascarello Aug 28 '20 at 14:13
  • @DannyHobo I tried running your code in Safari and can't reproduce the issue you're mentioning – Nick Parsons Aug 28 '20 at 14:14
  • @epascarello what does that mean? – Danny Hobo Aug 28 '20 at 14:17
  • @NickParsons yeah somehow the code snippet you made works for me in Safari as well. strange. – Danny Hobo Aug 28 '20 at 14:18
  • @DannyHobo that suggests that the issue is to do with something else in your code or your setup (ie: react version etc). Difficult to tell what exactly that might be though. – Nick Parsons Aug 28 '20 at 14:21
  • setTimeout 1000 is not exactly 1000 milliseconds and depending on the state of the browser/tab it may be even worse off. https://stackoverflow.com/questions/21097421/what-is-the-reason-javascript-settimeout-is-so-inaccurate – epascarello Aug 28 '20 at 14:21
  • @epascarello thanks, good info. but as the console.log does still fire I think that part is at least working as it should, even if it's not exactly 1000 milliseconds – Danny Hobo Aug 28 '20 at 14:33
  • @NickParsons just updated to latest version of React and still the same issue. obviously there is more in my code than just this but can't exactly upload the whole codebase here, besides it being too big it's also a client project :) – Danny Hobo Aug 28 '20 at 14:34

0 Answers0