Я следую учебнику для начинающих по хукам useState и useRef, пытаясь реализовать простой таймер в реакции.
Я использую переменную interval
для хранения значения из setInterval()
При нажатии кнопки запуска я могу правильно console.info значение интервала.
Однако при нажатии кнопки «Стоп» interval.current
регистрируется в консоли как undefined
. Следовательно, stopTimer()
не работает должным образом.
Почему interval.current печатает undefined, когда он явно установлен в startTimer (и зарегистрирован там)? Что мне здесь не хватает?
import React, { useState, useRef } from 'react';
const pad = (time) => {
return time.toString().padStart(2, "0");
};
function App() {
const [title, setTitle] = useState("Pomodoro!");
const [timeLeft, setTimeLeft] = useState(5);
const interval = useRef(null);
const startTimer = () => {
interval.current = setInterval(() => {
setTimeLeft((timeLeft) => {
if (timeLeft >= 1) {
return timeLeft - 1;
}
return 0;
});
}, 1000);
console.info(interval.current, " :in start");
}
const stopTimer = (interval) => {
console.info("in stop: ", interval.current);
clearInterval(interval.current);
}
const resetTimer = () => { }
const minutes = pad(Math.floor(timeLeft / 60));
const seconds = pad((timeLeft - minutes * 60));
return (
<div>
<div>{title}</div>
<div>
<span>{minutes}</span>
<span>:</span>
<span>{seconds}</span>
</div>
<div>
<button onClick = {startTimer}>Start</button>
<button onClick = {stopTimer}>Stop</button>
<button onClick = {resetTimer}>Reset</button>
</div>
</div>
);
}
export default App;
вывод в консоль
6 ": в начале" в остановке: не определено
Спасибо
Учитывая, что делает ваш код, я считаю, что interval
должна быть переменной состояния, а не ссылкой. То есть вы должны использовать
const [interval, setInterval] = useState(null);
вместо const interval = useRef(null);
Ссылки используются для привязки к элементам DOM (например, к элементу формы, на который вы хотите ссылаться при нажатии кнопки). Только когда переменная ref правильно ссылается на элемент DOM, определяется их атрибут current
.
Я полагаю, это потому, что вы передаете переменную более низкой области видимости, называемую interval
, в stopTimer
, но когда вы вызываете stopTimer
, вы не передаете аргумент, поэтому он не определен при доступе к нему.
Вероятно, вы имеете в виду interval
, который вы определили как ref
, поэтому вам нужно просто получить к нему доступ, не передавая interval
в stopTimer
, попробуйте следующее:
const stopTimer = () => {
console.info("in stop: ", interval.current);
clearInterval(interval.current);
}
Хотя ref часто используется для привязки элементов DOM, он этим не ограничивается.