Я хочу создать обратный таймер при нажатии кнопки.
Я создал setInterval с функцией, которая должна учитывать данные секунд и минут, а при нажатии на кнопку запуска секунды = 59 и уменьшаются на 1 каждую секунду, после этого при секундах = 0 минуты должны уменьшаться на 1, а секунд 59. Но после нажатия кнопки секунды = 59 а минуты -1, но обратного отсчета не происходит
const [time, setTime] = useState(10);
const [sec, setSec] = useState(0);
const [min, setMin] = useState(10);
let timerInt;
const timer=()=> {
timerInt = setInterval(timerF, 1000);
function timerF() {
if (sec===0){
setSec(59);
setMin(min - 1);
}
if (sec <= 0 && min <= 0) {
clearInterval(timerInt);
setSec(0);
setMin(0);
console.info('finish')
}
setSec(prev=>prev-1)
}
}
const handleStart = (time) => {
setMin(time)
setTime(time)
timer();
setDisabledBtn(true);
};
<div className = "time">
<div className = "time-min">{min}</div>
<span>:</span>
<div className = "time-sec">{sec}</div>
</div>
<button
className = "start-btn active-btn"
type = "button"
disabled = {disabledBtn && 'disabled'}
onClick = {() => handleStart(10)}
>
START
</button>
timerInt
тоже должен быть частью состояния, наверное.
Если min
это 1
и вы звоните setMin(min - 1)
min
все равно будет 1
. Он будет равен нулю в следующем цикле рендеринга.
Отвечает ли это на ваш вопрос? Метод set useState не сразу отражает изменение
В вашем случае setInterval
не имеет обновленного значения состояния реакции. Поэтому я создал аналогичную функциональность, используя useEffect и вызывая функцию timer()
с обновленным состоянием реакции. Я использовал setTimeout
, потому что мы привязываем и очищаем setTimeout
при каждом обновлении состояния. Так что нет смысла использовать setInterval в моем случае использования.
Обновленный и рабочий код ниже:
import React, {useState, useEffect} from 'react';
export function App(props) {
const [time, setTime] = useState(2);
const [sec, setSec] = useState(0);
const [min, setMin] = useState(2);
const [startTimer, setStartTimer] = useState(false);
let timerInt;
useEffect(() => {
if (startTimer) {
timer();
}
return () => {
clearTimeout(timerInt);
}
}, [min, sec, startTimer]);
const timer = () => {
const timerF = () => {
console.info("timer1", sec, min);
if (!sec){
setSec(59);
setMin(min - 1);
}
if (sec <= 0 && min <= 0) {
clearTimeout(timerInt);
setSec(0);
setMin(0);
setStartTimer(false);
console.info('finish')
}
setSec(prev=>prev-1)
}
timerInt = setTimeout(timerF, 1000);
}
const handleStart = (time) => {
setStartTimer(true);
setMin(time)
setTime(time);
};
return (
<div>
<div className = "time">
<div className = "time-min">{min}</div>
<span>:</span>
<div className = "time-sec">{sec}</div>
</div>
<button
className = "start-btn active-btn"
type = "button"
onClick = {() => handleStart(2)}
>
START
</button>
</div>
)
}
Попробуйте и дайте мне знать, если у вас все еще есть вопросы / проблемы.
Я немного модифицировал его, потому что в конце, когда обратный отсчет закончился, в поле секунд на экране было -1. Я исправил и все работает как надо! Спасибо!
FYI setInterval не является точным.