Search code examples
javascriptreactjsstaterefresh

Refreshing and updating useState/useRef in React


Trying to update and read state in React to switch between two different timers. I'm still new to programming and can't figure out why my component that displays the state "Session" or "Break" updates, but my conditional switchTimers() fails to switch timers based on that state.

const [timers, setTimers] = useState({
    sessionTime: 25,
    breakTime: 5,
  });
  const [timerDisplay, setTimerDisplay] = useState("Session");
  const [timerActive, setTimerActive] = useState(false)
  const [displayCount, setDisplayCount] = useState(1500);
  const round = useRef();

 function startStop(action, secondsLeft) {
    const interval = 1000;
    let expected = Date.now() + interval;
    if (action === "start") {
      setTimerActive(true)
      round.current = setTimeout(step, interval);
      function step() {
        if (secondsLeft > 0) {
        const drift = Date.now() - expected;
        setDisplayCount((prevValue) => prevValue - 1);
        secondsLeft --
        expected += interval;
        round.current = setTimeout(step, Math.max(0, interval - drift));
        } else {
          clearTimeout(round.current)
          switchTimers()
        }
      }
    } else if (action === "stop") {
      clearTimeout(round.current);
      setTimerActive(false);
    }
  }

  function switchTimers() {
    beep.current.play()
    if (timerDisplay === "Session") {
      setTimerDisplay("Break");
      setDisplayCount(timers.breakTime * 60);
      startStop("start", timers.breakTime * 60)
    } else if (timerDisplay === "Break") {
      setTimerDisplay("Session");
      setDisplayCount(timers.sessionTime * 60);
      startStop("start", timers.sessionTime * 60)
    }
  }

When the "Session" timer ends, it shows "Break" in my label that prints timerDisplay, but once "Break" timer ends, it reruns "Break" instead of switching to "Session". Any insight into whats going wrong?


Solution

  • Try writing you entire switchTimers function as a callback to the useEffect hook and add timerDisplay as a dependency. Also, please show the JSX you return from the component i.e. the entire code so that I can help you better.