Introduction
I am building the countdown timer, which I had built but now I want to scale it up. So I am building two countdowns on the same page with each of them having separate start
, stop
buttons, and common reset
button.
What do I have?
I have implemented but they are not working independently. For example, when I click on the stop of the upper clock, it also stops the lower clock.
What do I want?
I wanted to have separate functions for both of them but on the same page.
Code
Most of the things are repeated in the code.
import React, { useState, useEffect, useRef } from "react";
import "./styles.css";
const STATUS = {
STARTED: "Started",
STOPPED: "Stopped"
};
const STATUSp1 = {
STARTED: "Started",
STOPPED: "Stopped"
};
export default function InputCountDown() {
const [time, setTime] = useState(0);
const [timep1, setTimep1] = useState(0);
const [inc, setInc] = useState(0);
const handleOnChange = (e) => {
//console.log(e.target.value);
setTime(e.target.value);
setTimep1(e.target.value);
};
const handleOnChangeIncrement = (e) => {
console.log(e.target.value);
setInc(e.target.value);
};
const [secondsRemaining, setSecondsRemaining] = useState(time * 60);
const [secondsRemainingp1, setSecondsRemainingp1] = useState(timep1 * 60);
//console.log(time);
const [status, setStatus] = useState(STATUS.STOPPED);
const [statusp1, setStatusp1] = useState(STATUSp1.STOPPED);
const secondsToDisplay = secondsRemaining % 60;
const minutesRemaining = (secondsRemaining - secondsToDisplay) / 60;
const minutesToDisplay = minutesRemaining % 60;
const hoursToDisplay = (minutesRemaining - minutesToDisplay) / 60;
const secondsToDisplayp1 = secondsRemainingp1 % 60;
const minutesRemainingp1 = (secondsRemainingp1 - secondsToDisplayp1) / 60;
const minutesToDisplayp1 = minutesRemainingp1 % 60;
const hoursToDisplayp1 = (minutesRemainingp1 - minutesToDisplayp1) / 60;
const handleStart = () => {
setStatus(STATUS.STARTED);
setSecondsRemaining(time * 60);
};
const handleStartp1 = () => {
setStatusp1(STATUSp1.STARTED);
setSecondsRemainingp1(timep1 * 60);
};
const handleStop = () => {
setStatus(STATUS.STOPPED);
};
const handleStopp1 = () => {
setStatusp1(STATUSp1.STOPPED);
};
const handleReset = () => {
setStatus(STATUS.STOPPED);
setSecondsRemaining(time * 60);
setSecondsRemainingp1(timep1 * 60);
};
useInterval(
() => {
if (secondsRemaining > 0) {
setSecondsRemaining(secondsRemaining - 1);
} else {
setStatus(STATUS.STOPPED);
}
if (secondsRemainingp1 > 0) {
setSecondsRemainingp1(secondsRemainingp1 - 1);
} else {
setStatusp1(STATUSp1.STOPPED);
}
},
status === STATUS.STARTED ? 1000 : null,
statusp1 === STATUSp1.STARTED ? 1000 : null
// passing null stops the interval
);
return (
<>
<div className="App">
<h1>Countdown Using Input</h1>
<div style={{ padding: "12px" }}>
<label htmlFor="time"> Enter time in minutes </label>
<input
type="text"
id="time"
name="time"
value={time}
onChange={(e) => handleOnChange(e)}
/>
</div>
<div style={{ padding: "12px" }}>
<label htmlFor="inc"> Enter increment </label>
<input
type="number"
id="inc"
name="inc"
value={inc}
onChange={(e) => handleOnChangeIncrement(e)}
/>
</div>
<button onClick={handleStart} type="button">
Start
</button>
<button onClick={handleStop} type="button">
Stop
</button>
<button onClick={handleReset} type="button">
Reset
</button>
<div>
<button
onClick={() =>
setSecondsRemaining(secondsRemaining + parseInt(inc, 10))
}
>
Increment {inc} sec
</button>
</div>
<div style={{ padding: 20, fontSize: "40px" }}>
{twoDigits(hoursToDisplay)}:{twoDigits(minutesToDisplay)}:
{twoDigits(secondsToDisplay)}
</div>
<div>Status: {status}</div>
<div style={{ padding: 20, fontSize: "40px" }}>
{twoDigits(hoursToDisplayp1)}:{twoDigits(minutesToDisplayp1)}:
{twoDigits(secondsToDisplayp1)}
</div>
<button onClick={handleStartp1} type="button">
Start_p1
</button>
<button onClick={handleStopp1} type="button">
Stop_p1
</button>
<button onClick={handleReset} type="button">
Reset_p1
</button>
</div>
</>
);
}
// source: https://overreacted.io/making-setinterval-declarative-with-react-hooks/
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
// https://stackoverflow.com/a/2998874/1673761
const twoDigits = (num) => String(num).padStart(2, "0");
You can also find the code in the codesandbox in the inputCountDown.js
file .
You can ignore increment button
Please help me !!!