Hello everyone,
I’m encountering an issue with passing the last test of the 25 + 5 clock project. Despite trying several approaches, I’m unable to pass the following test:
“The audio element with id of ‘beep’ must stop playing and be rewound to the beginning when the element with the id of ‘reset’ is clicked.”
When I test this functionality myself, it works as expected; the reset button successfully pauses the audio element. However, during the actual test, it doesn’t seem to work. I suspect the issue might be related to timeouts.
I attempted to address this by optimizing the code with updated useEffect dependencies, and I even tried separating the useEffect specifically for the reset dependency. However, the outcome remained unchanged.
Additionally, if I add more if statements or control/state management conditions, such as context, it starts to fail other tests. While attempting to make the code faster, it seems that the useEffect becomes overloaded. I’ve spent the entire day trying to pass all of the tests, but unfortunately, I haven’t been successful.
Could you please help me determine whether this is due to a mistake on my part or an issue related to React 18? I’ve looked into React 18 issues, and it seems that most have been resolved by the great developers, but I’m still unsure.
If you want to see the codePen live version, firstly apologies for the messy code . It started with a different visual approach at the beginning, but it’s been growing bigger and bigger every day and I made a big challenge for my self… The relevant code for the app starts at line 677. To access the 25+5 clock, you should double-click on the shortcut; otherwise, it won’t render.
Also, when I set the interval to 1000ms, it sometimes causes some tests to fail. That’s why I set it to 999ms, but if this approach is not ethic, I can change although it might require changing the entire codebase …
Thank you…
const formatTime = (totalSeconds) => {
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
const formattedMinutes = minutes < 10 ? `0${minutes}` : `${minutes}`;
const formattedSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`;
return formattedMinutes+':'+formattedSeconds;
};
const CountdownTimer = ({ initialSeconds, onComplete, start, reset }) => {
const { volume } = useVolumeControl();
const audioElement = useRef(null)
const [seconds, setSeconds] = useState(initialSeconds);
const [timeInterval, setTimeInterval] = useState(null);
const [breakTimeout, setTimeoutState] = useState(null);
const secondUpdater = () => {
setSeconds((prevSeconds) => {
if (prevSeconds > 0) {
if (prevSeconds === 5) {
audioElement.current.src = countdownAudioSrc;
audioElement.current.play();
}
return prevSeconds - 1;
} else {
onComplete();
return 0;
}
});
}
useEffect(()=>{setSeconds(initialSeconds)},[initialSeconds])
useEffect(() => {
clearInterval(timeInterval);
clearTimeout(breakTimeout);
audioElement.current.pause();
audioElement.current.currentTime = 0;
audioElement.current.src = countdownAudioSrc;
if (reset) {
setSeconds(initialSeconds);
} else if (seconds === 0 && !reset) {
audioElement.current.src = alarmAudioSrc;
audioElement.current.play();
setSeconds(initialSeconds);
setTimeoutState(setTimeout(() => {
audioElement.current.pause();
audioElement.current.currentTime = 0;
}, 2000));
}
if (start) {
setTimeInterval(setInterval(secondUpdater, 999));
} else {
clearInterval(timeInterval);
}
}, [start, onComplete, reset]);
useEffect(() => {
if (audioElement.current) {
audioElement.current.volume = volume / 100;};
}, [volume]);
return (
<><audio id="beep" ref={audioElement}
src={countdownAudioSrc} loop/>
<div id='time-left'>{formatTime(seconds)}</div></>
);
};
const IntervalClock = () =>{
const [sessionLength, setSession] = useState(1500);
const [breakLength, setBreak] = useState(300);
const [breakMode, setBreakMode] = useState(false);
const [start, setStart] = useState(false);
const [reset, setReset] = useState(false);
const handleSessionComplete = () => {
setBreakMode(!breakMode)
};
const resetBtnHandler = () =>{
setReset(!reset);
setSession(1500);
setBreak(300);
setStart(false);
setBreakMode(false);
}
const handleOnChange = (event)=>{
(event.target.id==="session-range-input" || breakMode) && setReset(true);
const newValue = parseInt(event.target.value, 10);
event.target.id==="session-range-input" ? setSession(newValue * 60) : setBreak(newValue * 60)
}
return (
<div className="container">
<div className="time-container">
<div id="timer-label">
{breakMode ? "Break Time!" : "Session"}
</div>
<CountdownTimer
initialSeconds={breakMode ? breakLength : sessionLength}
onComplete={handleSessionComplete}
start={start}
reset={reset}
/>
</div>
<div className='box'>
<div className='label-box'><label id="session-label" for="session-range-input">
Session Length</label><div id='session-length'>{(sessionLength)/60}</div> <span>{formatTime(sessionLength)}</span>
</div>
<div className="input-box">
<button
className="btn"
id="session-decrement"
disabled={start}
onClick={() => setSession(Math.max(sessionLength - 60, 60))}
>
-
</button>
<input
id="session-range-input"
type="range"
min="1"
max="60"
value={sessionLength / 60}
disabled={start}
onChange={!start && handleOnChange}
/>
<button
className="btn"
disabled={start}
id="session-increment"
onClick={() => setSession(Math.min(sessionLength + 60, 3600))}
>
+
</button>
</div>
</div>
<div className='box'>
<div className='label-box'><label id="break-label" for="break-range-input">
Break Length</label><div id='break-length'>{(breakLength)/60}</div>
<span>{formatTime(breakLength)}</span>
</div>
<div className="input-box">
<button
className="btn"
disabled={start}
id="break-decrement"
onClick={() => setBreak(Math.max(breakLength - 60, 60))}
>
-
</button>
<input
id="break-range-input"
type="range"
min="1"
max="60"
value={breakLength / 60}
disabled={start}
onChange={!start && handleOnChange}
/>
<button
className="btn"
disabled={start}
id="break-increment"
onClick={() => setBreak(Math.min(breakLength + 60, 3600))}
>
+
</button>
</div>
</div>
<div className="button-container">
<button
class="btn"
style={{ width: "100px" }}
id="start_stop"
onClick={() => {
setStart(!start);
setReset(false);
}}
>
{start ? "Pause" : "Start"}
</button>
<button
class="btn"
style={{ width: "100px" }}
id="reset"
onClick={resetBtnHandler}
>
Reset
</button>
</div>
</div>
);
};