При повторном запуске таймера, он накладывается на предыдущий
Есть реактовский функциональный компонент, в нём есть таймер обратного отсчёта, который запускается по клику на кнопку. Оставшееся время выводится в html элемент, проблема в том, что при повторном клике на кнопку, запускается второй таймер обратного отсчёта и 2 таймера работают параллельно, о чём свидетельствует вывод в html.
Я хочу, что бы при запуске функции с таймером, проводилась проверка, не запущен-ли предыдущий таймер, если запущен - остановить прошлый и начать отсчёт заново, если не запущен - запустить
import React from "react";
import "./styles.css";
export default function App() {
const timer = (remainingMinutes, d, h, m, s) => {
var finishTime = new Date();
finishTime.setSeconds(finishTime.getSeconds() + remainingMinutes);
let timeLeft = document.getElementById("timer");
var timesOver;
function update() {
// сколько осталось миллисекунд
var diff = finishTime - new Date();
// сколько миллисекунд до конца секунды
var millis = diff % 1000;
diff = Math.floor(diff / 1000);
// сколько секунд до конца минуты
var sec = diff % 60;
if (sec < 10) sec = "0" + sec;
diff = Math.floor(diff / 60);
// сколько минут до конца часа
var min = diff % 60;
if (min < 10) min = "0" + min;
diff = Math.floor(diff / 60);
// сколько часов до конца дня
var hours = diff % 24;
if (hours < 10) hours = "0" + hours;
var days = Math.floor(diff / 24);
d = +days;
h = +hours;
m = +min;
s = +sec;
timeLeft.innerHTML = `Offer is valid for ${m} minutes ${s} seconds`;
// возвращаем оставшееся колличество секунд
timesOver = d * 86400 + h * 3600 + m * 60 + s;
// Если время закончилось - выводим заглушку
if (timesOver === 0) {
return (timeLeft.innerHTML = `Offer timed out`);
}
// следующий раз вызываем себя, когда закончится текущая секунда
setTimeout(update, millis);
}
setTimeout(update, 0);
};
return (
<div className="App">
<h4 id="timer">TIMER</h4>
<button onClick={() => timer(30)}>Start Timer </button>
</div>
);
}
Наглядный пример. Если кликнуть по кнопке раз 5 подряд, видно, что время в заголовке начинает "прыгать"
Ответы (1 шт):
Автор решения: Евгений Платов
→ Ссылка
let temp = 0;
const timer = (remainingMinutes, d, h, m, s) => {
var finishTime = new Date();
finishTime.setSeconds(finishTime.getSeconds() + remainingMinutes);
let timeLeft = document.getElementById("timer");
var timesOver;
function update() {
// сколько осталось миллисекунд
var diff = finishTime - new Date();
// сколько миллисекунд до конца секунды
var millis = diff % 1000;
diff = Math.floor(diff / 1000);
// сколько секунд до конца минуты
var sec = diff % 60;
if (sec < 10) sec = "0" + sec;
diff = Math.floor(diff / 60);
// сколько минут до конца часа
var min = diff % 60;
if (min < 10) min = "0" + min;
diff = Math.floor(diff / 60);
// сколько часов до конца дня
var hours = diff % 24;
if (hours < 10) hours = "0" + hours;
var days = Math.floor(diff / 24);
d = +days;
h = +hours;
m = +min;
s = +sec;
timeLeft.innerHTML = `Offer is valid for ${m} minutes ${s} seconds`;
// возвращаем оставшееся колличество секунд
timesOver = d * 86400 + h * 3600 + m * 60 + s;
// Если время закончилось - выводим заглушку
if (timesOver === 0) {
return (timeLeft.innerHTML = `Offer timed out`);
}
// следующий раз вызываем себя, когда закончится текущая секунда
clearTimeout(temp);
temp = setTimeout(update, millis);
}
setTimeout(update, 0);
};