25+5 React project doesn't pass 4 tests even though it should

Dear fcc community,
I’m reaching out to you because I am at the end of my rope. I have been doing this challenge for almost a year (on and off) and my peabrain can’t skip this, because I want to finish the curriculum in order.
Can anyone tell what is wrong, what I’m doing wrong, or how else to to get these tests to pass, because at this point I’m honestly frustrated and it isn’t fun anymore… especially regarding issue no.8, because I disabled the changing of the sessionLength while in a session. The audio issues are also a total mystery to me, because you can hear the sounds and everything works correctly while using the app. I don’t want to go that far and assume the tests are broken, but are they in this case (without insult to the testmakers)? Because I am really out of ideas what to do anymore…

Issues:

    1. When I first click the element with id=“start_stop”, the timer should begin running from the value currently displayed in id=“session-length”, even if the value has been incremented or decremented from the original value of 25.

expected ‘60’ to equal ‘25’

  • all the audio tests are not passing…
import React, { useState, useEffect } from 'react';
import './App.css';
 
function PomodoroApp() {
  const [sessionLength, setSessionLength] = useState(25);
  const [breakLength, setBreakLength] = useState(5);
  const [minutes, setMinutes] = useState(sessionLength);
  const [seconds, setSeconds] = useState(0);
  const [isActive, setIsActive] = useState(false);
  const [isBreak, setIsBreak] = useState(false);
  // add isWork status regarding issue #8
  const [isWork, setIsWork] = useState(false);
 
  useEffect(() => {
    let interval;
 
    if (isActive) {
      interval = setInterval(() => {
        if (seconds === 0) {
          if (minutes === 0) {
            // Timer is up, switch to break or work
            setIsBreak(!isBreak);
            setMinutes(isBreak ? sessionLength : breakLength);
          } else {
            setMinutes(minutes - 1);
            setSeconds(59);
          }
        } else {
          setSeconds(seconds - 1);
        }
      }, 1000);
 
      // Check if the timer ended and play an alert sound
      if (minutes === 0 && seconds === 0) {
        const audio = new Audio(
          'https://www.soundjay.com/misc/sounds/pill-bottle-2.mp3'
        );
        audio.play();
      }
    } else {
      clearInterval(interval);
    }
 
    return () => clearInterval(interval);
  }, [isActive, minutes, seconds, isBreak, sessionLength, breakLength]);
 
  const toggleTimer = () => {
    setIsActive(!isActive);
    setIsWork(true);
  };
 
  const resetTimer = () => {
    setIsWork(false);
    setIsActive(false);
    setIsBreak(false);
    setMinutes(sessionLength);
    setSeconds(0);
    //
    setSessionLength(25);
    setBreakLength(5);
  };
 
  const increaseSessionLength = () => {
    // check if isWork is inactive and only then change is possible?
    if (!isActive && !isWork && sessionLength < 60) {
      setSessionLength(sessionLength + 1);
      setMinutes(sessionLength + 1);
    }
  };
 
  const decreaseSessionLength = () => {
    if (!isActive && !isWork && sessionLength > 1) {
      setSessionLength(sessionLength - 1);
      setMinutes(sessionLength - 1);
    }
  };
 
  const increaseBreakLength = () => {
    if (!isActive && !isWork && breakLength < 60) {
      setBreakLength(breakLength + 1);
    }
  };
 
  const decreaseBreakLength = () => {
    if (!isActive && !isWork && breakLength > 1) {
      setBreakLength(breakLength - 1);
    }
  };
 
  return (
    <div className="pomodoro-app">
      <h1 id="timer-label">{isBreak ? 'Break' : 'Work'}</h1>
      <div id="time-left">
        {String(minutes).padStart(2, '0')}:{String(seconds).padStart(2, '0')}
      </div>
      <audio id="beep">
        <source src="" />
      </audio>
      <div className="controls">
        <button onClick={toggleTimer} id="start_stop">
          {isActive ? 'Pause' : 'Start'}
        </button>
        <button onClick={resetTimer} id="reset">
          Reset
        </button>
      </div>
      <div className="length-controls">
        <div className="session">
          <p id="session-label">Session Length</p>
          <button onClick={increaseSessionLength} id="session-increment">
            +
          </button>
          <span id="session-length">{sessionLength}</span>
          <button onClick={decreaseSessionLength} id="session-decrement">
            -
          </button>
        </div>
        <div className="break">
          <p id="break-label">Break Length</p>
          <button onClick={increaseBreakLength} id="break-increment">
            +
          </button>
          <span id="break-length">{breakLength}</span>
          <button onClick={decreaseBreakLength} id="break-decrement">
            -
          </button>
        </div>
      </div>
      {/* {minutes == 0 && seconds == 0 && (
        <audio src=https://www.soundjay.com/misc/sounds/pill-bottle-2.mp3 id="beep" />
      )} */}
      <audio src='https://www.soundjay.com/misc/sounds/pill-bottle-2.mp3' id="beep" />
    </div>
  );
}
 
export default PomodoroApp;

Can anyone shed some light on the issue for me and tell me what is going on? Would be greatly appreciated. Thank you all in advance for reading this and looking forward to your comments.

The setMinutes setter inside the reset handler should always be set to the same value as you are setting setSessionLength to. You can just hardcode 25 as the value for that setter as well (instead of sessionLength).

The audio must be a file in the HTML (JSX) so the test can access its properties.

The element with the audio file must be the only element with the beep id on it. You should not have more than one element with that id.

You should pause and reset the currentTime on the audio element in your reset handler.

You can use a ref to get to the audio element (docs).

2 Likes

do you. have a link to a codepen of this?

I think you are relying on useEffect to do way too much in this component, and when you have so many dependencies you can get some very unexpected results.

I just created a flashcard app that had multiple useEffect calls and by restructuring the components I was able to get rid of all of them.

Not sure this helps , but I DO understand your frustration with working on one project for a long time and not having it pass. heck…i worked on one of the d3 projects for 7 years! ( no joke…the heat man exercise)

The useEffect is fine for what it is used for. It is hard to make a timer without it.

All they need to do is not use sessionLength for the setMinutes in the reset handler (and fix the audio stuff as well).

2 Likes

Thank you Lasse, you saved my life. I would have never caught the small bug in the reset handler. Great catch.

Here is the codepen (https://codepen.io/vuking/pen/rNPQWvZ?editors=1111).

I have another question though: how to get React to work within the codepen, as nothing gets rendered and I get a mysterious [object Error] {} in the console.
I found your solution (to the same issue) here: (TypeError: ReactDOM.render is not a functionIn codepen), however even with the imports nothing gets rendered (Edit: I can see a brief flash of the rendering on ‘myPens’ when it loads the preview). Thank you again Lasse for saving my life. Any idea to get this working within codepen?

1 Like

I can see you got it working.

As an aside, I would use Stackblitz or Codesandbox for framework code. Their editor is also just nicer and more like a local setup.

Anyway, good job finishing the project and passing all the tests. :tada:

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.