Front End Development Libraries Projects - Build a 25 + 5 Clock

Tell us what’s happening:

Test #11 is failing and I am not sure why because it is working perfectly fine when I test it manually on my end. The error message I get is:

Default timer label was not properly reset : expected ‘Break’ to equal ‘Session’. Any help or hint would be much appreciated. Thanks in advance :slight_smile:

Your code so far

<div id="App"></div>
const Pomodoro = () => {
  [times, setTimes] = React.useState({
    breakLength: 5, //5,
    sessionLength: 25, //25,
    timerCount: 1500, //1500,
    timerStatus: "idle", // idle, running, paused
    timerLabel: "Session"
  });
  
  adjustLength = (breakOrSession, upOrDown) => {
    if (breakOrSession === "break") {
      if (upOrDown === "up" && times.breakLength < 60) {
        setTimes((prevSet) => ({
          ...prevSet,
          breakLength: prevSet["breakLength"] + 1
        }))
      } else if (upOrDown === "down" && times.breakLength > 1) {
        setTimes((prevSet) => ({
          ...prevSet,
          breakLength: prevSet["breakLength"] - 1
        }))
      }
    } else if (breakOrSession === "session") {
      if (upOrDown === "up" && times.sessionLength < 60) {
        setTimes((prevSet) => ({
          ...prevSet,
          sessionLength: prevSet["sessionLength"] + 1
        }))
      } else if (upOrDown === "down" && times.sessionLength > 1) {
        setTimes((prevSet) => ({
          ...prevSet,
          sessionLength: prevSet["sessionLength"] - 1
        }))
      }
    }
    setTimes((prevSet) => ({
      ...prevSet,
      timerCount: prevSet["sessionLength"] * 60
    }))
  }
  
  startTimer = () => {
    setTimes((prevSet) => ({
      ...prevSet,
      timerStatus: prevSet["timerStatus"] === "idle" || prevSet["timerStatus"] === "paused" ? "running" : "paused" 
    }))
  }
  
  refreshActivity = () => {
    setTimes((prevSet) => ({
        ...prevSet,
      timerStatus: "idle",
      breakLength: 5,
      sessionLength: 25,
      timerCount: 1500,
      timerLabel: "Session"
    }))
  }
  
  
  React.useEffect(() => {
    if (times.timerCount === 0) {
      document.getElementById("beep").play();
      setTimes((prevSet) => ({
        ...prevSet,
        timerLabel: prevSet["timerLabel"] === "Break" ? "Session" : "Break"
      }))
    }
  }, [times.timerCount]);
  
  React.useEffect(() => {
  if (times.timerStatus === "running") {
    const intervalId = setInterval(() => {
      setTimes((prevSet) => ({
        ...prevSet,
        timerCount: prevSet["timerCount"] - 1,
      }));
    }, 990);
    if (times.timerCount === 0) {
      setTimes((prevSet) => ({
        ...prevSet,
        timerCount: times.timerLabel === "Break" ? times.breakLength * 60 : times.sessionLength * 60
      }))
    }
    
    // Cleanup function to prevent multiple intervals
    return () => clearInterval(intervalId);
  }
}, [times.timerStatus, times.timerLabel]); // Only runs when times.timerStatus changes
  
  displayRemainingTime = () => {
    const minuteDisplay = Math.floor(times.timerCount / 60) < 10 ? '0' + Math.floor(times.timerCount / 60) : Math.floor(times.timerCount / 60);
    const secondDisplay = times.timerCount % 60 < 10 ? '0' + times.timerCount % 60 : times.timerCount % 60;
    return (`${minuteDisplay}:${secondDisplay}`)
  }
  
  
  return (
    <div id="pomodoro-container">
      <h1 id="header">
        Pomodoro clock
      </h1>
      <div id="break-session-length">
        <div id="break">
          <h2 id="break-label">Break Length</h2>
          <div id="break-control">
            <i className="fa fa-arrow-down fa-2x" id="break-decrement" onClick={() => {adjustLength("break", "down")}}></i>
            <span id="break-length">{times.breakLength}</span>
            <i className="fa fa-arrow-up fa-2x" id="break-increment" onClick={() => adjustLength("break", "up")}></i>
          </div>
        </div>
        <div id="session">
          <audio id="beep" preload="auto" src="https://cdn.freecodecamp.org/testable-projects-fcc/audio/BeepSound.wav"></audio>
          <h2 id="session-label">Session Length</h2>
          <div id="session-control">
            <i className="fa fa-arrow-down fa-2x" id="session-decrement" onClick={() => adjustLength("session", "down")}></i>
            <span id="session-length">{times.sessionLength}</span>
            <i className="fa fa-arrow-up fa-2x" id="session-increment" onClick={() => adjustLength("session", "up")}></i>
          </div>
        </div>
      </div>
      <div id="session">
        <h2 id="timer-label">{times.timerLabel}</h2>
        <div id="time-left">{displayRemainingTime()}</div>
      </div>
      <div id="buttons">
        <button id="start_stop" onClick={startTimer}>
          <i className="fa fa-play fa-2x"></i>
          <i className="fa fa-pause fa-2x"></i>
        </button>
        <button id="reset">
          <i className="fa fa-refresh fa-2x" onClick={refreshActivity}></i>
        </button>
      </div>
    </div>
  )
}

ReactDOM.render(<Pomodoro/>, document.getElementById("App"))

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:134.0) Gecko/20100101 Firefox/134.0

Challenge Information:

Front End Development Libraries Projects - Build a 25 + 5 Clock

Try rewriting this so it doesn’t use an updater function. (Just call setTimes with the new object directly)
I don’t know if it will help but maybe it won’t be queued behind other renders this way.

If that doesn’t help then maybe try a flush sync to see if it works better with these tests. Learn more here < React 18: Automatic Batching. In this article, you are going to read… | by Kaan Alboy | JavaScript in Plain English>

Thank you for replying. I have rewritten the update function as you mentioned and I have tried the flush sync but I am failing the same tests. :frowning:

Are you failing more than one test?

I pass all the tests in the #contents section but I am failing majority of tests following. Again when I test them manually it works as intended.

Any more ideas by any chance? :slight_smile:

Unfortunately without testing your actual code I am not sure what else to offer. Knowing which tests are failing may offer a clue as maybe one is cascading into the others (but the real issue may be one specific one)

You can also try using a callback function and pass it to useState here in order to make sure that this initializer only runs once (and not on every render).
Reference: useState – React

You can also try to use the flush sync in more places…

Also noticed this. I think it should be every 1000, not 990?

To get better help, please provide a live example using Stackblitz, Codesandbox, Codepen, or a repo.


  • Why are you not declaring your variables/functions?

  • Move your reset click handler to the reset button element.

  • Your reset function should also reset the audio element (must stop playing and be rewound to the beginning).

  • At some point, the session time gets set to a negative value by the test, I didn’t try debugging it to figure out how or why.

Thank you. I will try this and I will get back to you. :slight_smile: