I am trying to complete the FreeCodeCamp 25 + 5 clock project with React. When I website runs the project tests, it says that the timer is not reaching 00:00, even though when I click play, it clearly reaches 00:00.
I am wondering if I am having this issue because of some sort of drifting? How would I go about fixing that?
Thank you.
Codepen: https://codepen.io/Jamece/pen/jOazYvQ
I also tried a version where i use SetTimeout and implement this Stack overflow answer (setInterval timing slowly drifts away from staying accurate), but it still wouldn’t pass the test. See that codepen: https://codepen.io/Jamece/pen/mdqGomq
I also tried delaying the this.atZero function 1 second and that didn’t work
My Code:
const minTime = 1;
const maxTime = 60;
class Application extends React.Component {
constructor(props) {
super(props);
this.state = {
breakLength: .1,
sessionLength: .1,
started: false,
mode: "Session",
intervalId: "",
timeLeft: .1
};
this.breakIncrement = this.breakIncrement.bind(this);
this.breakDecrement = this.breakDecrement.bind(this);
this.sessionIncrement = this.sessionIncrement.bind(this);
this.sessionDecrement = this.sessionDecrement.bind(this);
this.sessionTimer = this.sessionTimer.bind(this);
this.breakTimer = this.breakTimer.bind(this);
this.pause = this.pause.bind(this);
this.timers = this.timers.bind(this);
this.initialDisplay = this.initialDisplay.bind(this);
this.switchMode = this.switchMode.bind(this);
this.begin = this.begin.bind(this);
this.reset = this.reset.bind(this);
this.atZero = this.atZero.bind(this);
}
initialDisplay() {
let initialDisplay =
this.state.sessionLength < 10
? "0" + this.state.sessionLength + ":" + "00"
: this.state.sessionLength + ":" + "00";
return initialDisplay;
}
begin() {
this.setState({ started: !this.state.started });
if (this.state.started) {
this.pause();
} else {
if (this.state.mode == "Session") {
this.sessionTimer();
} else {
this.breakTimer();
}
}
}
atZero(){
var audio = document.getElementById("beep");
clearInterval(this.state.intervalId);
this.switchMode();
audio.play();
}
switchMode() {
if (this.state.mode == "Session") {
this.setState({
mode: "Break",
timeLeft: this.state.breakLength
});
this.breakTimer();
} else if (this.state.mode == "Break") {
this.setState({
mode: "Session",
timeLeft: this.state.sessionLength
});
this.sessionTimer();
}
}
breakIncrement() {
if (!this.state.started) {
if (this.state.breakLength !== maxTime) {
this.setState((state) => ({
breakLength: state.breakLength + 1
}));
}
}
}
breakDecrement() {
if (!this.state.started) {
if (this.state.breakLength !== minTime) {
this.setState((state) => ({
breakLength: state.breakLength - 1
}));
}
}
}
sessionIncrement() {
if (!this.state.started) {
if (this.state.sessionLength !== maxTime) {
this.setState((state) => ({
sessionLength: state.sessionLength + 1
}));
}
}
}
sessionDecrement() {
if (!this.state.started) {
if (this.state.sessionLength !== minTime) {
this.setState((state) => ({
sessionLength: state.sessionLength - 1
}));
}
}
}
timers(length, display, paused) {
var start = Date.now();
const timer = () => {
const distance = (length) - (((Date.now() - start) / 1000) | 0);
var minutes = (distance / 60) | 0;
var seconds = distance % 60 | 0;
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
this.setState({ timeLeft: distance / 60 });
const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
};
if (distance < 0) {
this.atZero();
}
};
timer();
var intervalId = setInterval(timer,1000);
this.setState({
intervalId: intervalId
});
}
sessionTimer() {
var length = this.state.timeLeft * 60;
var display = document.getElementById("time-left");
this.timers(length, display);
this.setState({ started: true });
}
breakTimer() {
var length = this.state.timeLeft * 60;
var display = document.getElementById("time-left");
this.timers(length, display);
this.setState({ started: true });
}
pause() {
if (this.state.intervalId) {
clearInterval(this.state.intervalId);
}
this.setState({ started: !this.state.started });
}
reset() {
clearInterval(this.state.intervalId);
this.setState({
breakLength: 5,
sessionLength: 25,
started: false,
mode: "Session",
intervalId: "",
timeLeft: 25
});
let resetValue = this.initialDisplay();
let resetDisplay = document.getElementById("time-left");
resetDisplay.textContent = resetValue;
var audio = document.getElementById("beep");
audio.pause();
audio.currentTime = 0;
}
render() {
let pausePlayStyle = this.state.started
? "fa-solid fa-pause"
: "fa-solid fa-play";
return (
<div className="container-fluid px-0">
<div className="main d-flex justify-content-center align-items-center">
<div className="d-flex flex-column align-items-center">
<div className="heading">25 + 5 Clock</div>
<div className="d-flex">
<div className="d-flex flex-column break align-items-center">
<div id="break-label" className="mb-3 h3">
Break Length
</div>
<div className="d-flex flex-row">
<button
className="btn btn-top"
id="break-increment"
onClick={this.breakIncrement}
>
<i class="fa-solid fa-arrow-up"></i>
</button>
<div className="mx-3 h3" id="break-length">
{this.state.breakLength}
</div>
<button
className="btn btn-top"
id="break-decrement"
onClick={this.breakDecrement}
>
<i class="fa-solid fa-arrow-down"></i>
</button>
</div>
</div>
<div className="d-flex flex-column align-items-center session">
<div id="session-label" className="mb-3 h3">
Session Length
</div>
<div className="d-flex flex-row">
<button
className="btn btn-top"
id="session-increment"
onClick={this.sessionIncrement}
>
<i class="fa-solid fa-arrow-up"></i>
</button>
<div className="h3 mx-3" id="session-length">
{this.state.sessionLength}
</div>
<button
className="btn btn-top"
id="session-decrement"
onClick={this.sessionDecrement}
>
<i class="fa-solid fa-arrow-down"></i>
</button>
</div>
</div>
</div>
<div className="d-flex flex-column align-items-center timer-border">
<div className="h2 mb-3 session" id="timer-label">
{this.state.mode}
</div>
<div className="display-1 timer mb-4" id="time-left">
{this.initialDisplay()}
</div>
<div className="d-flex flex-row">
<button
className="btn btn-bottom"
id="start_stop"
onClick={this.begin}
>
<i className={pausePlayStyle}></i>
</button>
<button
className="btn btn-bottom"
id="reset"
onClick={this.reset}
>
<i className="fa-solid fa-rotate"></i>
</button>
</div>
</div>
</div>
</div>
<audio
id="beep"
preload ="auto"
src="https://docs.google.com/uc?export=download&id=12NsFWtJh3pBCqQ8gV62EZF3OevgAy8ff"
/>
</div>
);
}
}
ReactDOM.render(<Application />, document.getElementById("root"));