Pomodoro Clock - pause/reset functionality problem

Hey guys, getting stuck into the Pomodoro Clock challenge for the front end libraries portion of the curriculum and I’ve exhausted every option I can think of, so thought it was time to ask for help.

Project link: https://www.freecodecamp.org/learn/front-end-libraries/front-end-libraries-projects/build-a-pomodoro-clock

Problem

I am having an issue with resetting the time whilst it is running on a button click. I have a function resetTimer which is currently being used to reinitialise the timer and break count at the end of each cycle, but if clicked whilst either timer or break is running (counting down to 0), then resetTimer does indeed run for a second but then the timer carries on as it did before the button firing the event.

What I’ve tried

I have tried calling resetTimer and return if a condition resetClicked === true which calls the function and it runs briefly but then carries on with the original timer.

I’ve also tried setting an initialising function which checks if resetClicked === true before calling the start() function and then calling this again in resetTimer but didn’t work either.

Code

import React, { useState } from "react";

export default function App() {
  const [sessionLength, setSessionLength] = useState(25);
  const [breakLength, setBreakLength] = useState(5);
  const [timerRunning, setTimerState] = useState(false);
  const [breakRunning, setBreakState] = useState(false);

  let countdown;
  let minutesToSecondsSession = sessionLength * 60;
  let minutestoSecondsBreak = breakLength * 60;
  const clear = () => clearInterval(countdown);

  const start = () => {
    if (timerRunning === false) {
      setTimerState(true);
      console.log("timer started");
      const now = Date.now();
      const then = now + minutesToSecondsSession * 1000;

      displayTimeLeftSession(minutesToSecondsSession);

      countdown = setInterval(() => {
        const secondsLeft = Math.round((then - Date.now()) / 1000);

        if (secondsLeft === 0) {
          clear(countdown);
          console.log("timer interval cleared");
          breakTimer();
        }

        displayTimeLeftSession(secondsLeft);
      }, 1000);
    }
  };
  // end of timer function
  //
  // start of break timer
  function breakTimer() {
    if (breakRunning === false) {
      setBreakState(true);
      console.log("break timer started");
      const now = Date.now();
      const then = now + minutestoSecondsBreak * 1000;

      displayTimeLeftBreak(minutestoSecondsBreak);

      countdown = setInterval(() => {
        const secondsLeft = Math.round((then - Date.now()) / 1000);

        if (secondsLeft === 0) {
          console.log("break interval cleared");
          resetTimer();
          return;
        }

        displayTimeLeftBreak(secondsLeft);
      }, 1000);
    }
  }

  function displayTimeLeftSession(minutesToSecondsSession) {
    const minutes = Math.floor(minutesToSecondsSession / 60);
    const remainderSeconds = minutesToSecondsSession % 60;

    setSessionLength(`${minutes}:${remainderSeconds}`);
  }

  function displayTimeLeftBreak(minutesToSecondsBreak) {
    const minutes = Math.floor(minutesToSecondsBreak / 60);
    const remainderSeconds = minutesToSecondsBreak % 60;

    setBreakLength(`${minutes}:${remainderSeconds}`);
  }

  // end of display timer logic

  function incrementSession() {
    if (sessionLength <= 60) {
      setSessionLength(prev => prev + 1);
    }
  }

  function decrementSession() {
    if (sessionLength > 1) {
      setSessionLength(prev => prev - 1);
    }
  }

  function incrementBreak() {
    if (breakLength < 60) {
      setBreakLength(prev => prev + 1);
    }
  }

  function decrementBreak() {
    if (breakLength > 1) {
      setBreakLength(prev => prev - 1);
    }
  }

  const resetTimer = () => {
    clear(countdown);
    setTimerState(false);
    setBreakState(false);
    setSessionLength(0.05);
    setBreakLength(0.05);
    console.log("reset");
  };

Code is up until return(), have omitted the JSX to save space, just renders the timer onto the page anyway, had issues adding an embed.

https://codesandbox.io/s/fcc-pomodoro-clock-3rxfh?fontsize=14&hidenavigation=1&theme=dark

Edit

Tried separating the countdown variable in the global scope to individual variables for the session and break timer specifically to allow clearInterval to target each individual function but had the same problem with the timer continuing the run.

import React, { useState, useRef } from "react";

export default function App() {
  const [breakLength, setBreakLength] = useState(0.05);
  const [sessionLength, setSessionLength] = useState(20);
  const [timerRunning, setTimerState] = useState(false);
  const [breakRunning, setBreakState] = useState(false);

  let sessionCountdown;
  let breakCountdown;
  let minutesToSecondsSession = sessionLength * 60;
  let minutestoSecondsBreak = breakLength * 60;
  //const clear = () => clearInterval(countdown);

  const start = () => {
    if (timerRunning === false) {
      setTimerState(true);
      console.log("timer started");
      const now = Date.now();
      const then = now + minutesToSecondsSession * 1000;

      displayTimeLeftSession(minutesToSecondsSession);

      sessionCountdown = setInterval(() => {
        const secondsLeft = Math.round((then - Date.now()) / 1000);

        if (secondsLeft === 0) {
          clearInterval(sessionCountdown);
          console.log("timer interval cleared");
          breakTimer();
        }

        displayTimeLeftSession(secondsLeft);
      }, 1000);
    }
  };
  // end of timer function
  //
  // start of break timer
  function breakTimer() {
    if (breakRunning === false) {
      setBreakState(true);
      console.log("break timer started");
      const now = Date.now();
      const then = now + minutestoSecondsBreak * 1000;

      displayTimeLeftBreak(minutestoSecondsBreak);

      breakCountdown = setInterval(() => {
        const secondsLeft = Math.round((then - Date.now()) / 1000);

        if (secondsLeft === 0) {
          console.log("break interval cleared");
          clearInterval(breakCountdown);
          resetTimer();
          return;
        }

        displayTimeLeftBreak(secondsLeft);
      }, 1000);
    }
  }

  function displayTimeLeftSession(minutesToSecondsSession) {
    const minutes = Math.floor(minutesToSecondsSession / 60);
    const remainderSeconds = minutesToSecondsSession % 60;

    setSessionLength(`${minutes}:${remainderSeconds}`);
  }

  function displayTimeLeftBreak(minutesToSecondsBreak) {
    const minutes = Math.floor(minutesToSecondsBreak / 60);
    const remainderSeconds = minutesToSecondsBreak % 60;

    setBreakLength(`${minutes}:${remainderSeconds}`);
  }

  // end of display timer logic

  function incrementSession() {
    if (sessionLength <= 60) {
      setSessionLength(prev => prev + 1);
    }
  }

  function decrementSession() {
    if (sessionLength > 1) {
      setSessionLength(prev => prev - 1);
    }
  }

  function incrementBreak() {
    if (breakLength < 60) {
      setBreakLength(prev => prev + 1);
    }
  }

  function decrementBreak() {
    if (breakLength > 1) {
      setBreakLength(prev => prev - 1);
    }
  }

  const resetTimer = () => {
    clearInterval(sessionCountdown);
    clearInterval(breakCountdown);
    setTimerState(false);
    setBreakState(false);
    setSessionLength(0.05);
    setBreakLength(0.05);
    console.log("reset");
  };

It’s because in the “start” function, you start/stop only if TimerRunning === false. But the timer is running, so nothing happens. TimerRunning needs to be set to true.