Это потому, что ваш код закрывает значение currentSecond
от рендера до того, как вы нажали кнопку. То есть javascript не знает о повторных рендерах и хуках. Вы хотите настроить это немного по-другому.
import React, { useState, useRef, useEffect } from 'react';
const Play = ({ secondsPerRep }) => {
const secondsPassed = useRef(1)
const [currentSecond, setCurrentSecond] = useState(1);
const [timerStarted, setTimerStarted] = useState(false)
useEffect(() => {
let timer;
if(timerStarted) {
timer = setInterval(() => {
if (secondsPassed.current < secondsPerRep) {
secondsPassed.current =+ 1
setCurrentSecond(secondsPassed.current)
}
}, 1000);
}
return () => void clearInterval(timer)
}, [timerStarted])
return (
<div>
<div>
<button onClick={() => setTimerStarted(!timerStarted)}>
{timerStarted ? Stop : Start}
</button>
<p>{currentSecond}</p>
</div>
</div>
);
}
export default Play;
Зачем вам нужен ref
и состояние? Если у вас будет только состояние, метод очистки эффекта будет запускаться каждый раз, когда вы обновляете свое состояние. Следовательно, вы не хотите, чтобы ваше состояние влияло на ваш эффект. Вы можете достичь этого, используя ref
для подсчета секунд. Изменения в ссылке не приведут к запуску эффекта или его очистке.
Однако вам также необходимо состояние, потому что вы хотите, чтобы ваш компонент повторно отображал после выполнения вашего условия. Но поскольку методы средства обновления для состояния (т. Е. setCurrentSecond
) являются постоянными, они также не влияют на эффект.
И последнее, но не менее важное: я отделился, установив интервал из вашей логики подсчета c , Я сделал это с дополнительным состоянием, которое переключается между true
и false
. Поэтому, когда вы нажимаете кнопку, состояние переключается на true
, эффект запускается и все настраивается. Если ваши компоненты отключены, или вы остановили таймер, или secondsPerRep
реквизит изменяет старый интервал, очищается и устанавливается новый.
Надеюсь, это поможет!