#javascript #html #css #reactjs #jsx
#javascript #HTML #css #reactjs #jsx
Вопрос:
Итак, я создаю приложение для медитации в React. Для начала я дал ему 25-минутный обратный отсчет.
Я хочу, чтобы обратный отсчет начинался при нажатии кнопки. Однако, когда я переношу setInterval в функцию handleClick(), секунды уменьшаются за клик, а не запускают обратный отсчет один раз.
Любая помощь приветствуется, заранее спасибо.
import React, { Component, useState } from "react";
function Timer() {
const [minutes, setMinutes] = useState(25);
const [seconds, setSeconds] = useState(0);
function handleClick() {
console.log('Clicked');
let interval = setInterval(() => {
clearInterval(interval);
if (seconds === 0) {
if (minutes !== 0) {
setSeconds(59);
setMinutes(minutes - 1);
} else {
setSeconds(seconds - 1);
}
}, 1000)
}
const timerMinutes = minutes < 10 ? `0${minutes}`: minutes;
const timerSeconds = seconds < 10 ? `0${seconds}` : seconds;
return (
<>
<div className="grey-box">
<div className="number-box">
<h2 className="timer-text">{timerMinutes}:{timerSeconds}</h2>
</div>
<div className="buttons-container">
<button className="timer-button" onClick={handleClick}>
<img
className="play"
src="https://img.icons8.com/ios-glyphs/90/ffffff/play--v1.png"
/>
</button>
</div>
</div>
</>
);
}
export default Timer;
Комментарии:
1. Вы немедленно очищаете интервал без условия, т.Е. Очищаете, не проверяя, завершен ли обратный отсчет
Ответ №1:
Вы создаете таймер гораздо более сложным способом. Я сделал образец, который может охватить этот вариант использования вместе с некоторыми крайними случаями.
import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function ClearTimer(TimerHndlRef) {
clearInterval(TimerHndlRef.current);
TimerHndlRef.current = null;
}
function App() {
const TimerHndlRef = useRef();
const [seconds, secondsSet] = useState(5);
const onClick = () => {
if (TimerHndlRef.current) {
ClearTimer(TimerHndlRef);
return;
}
TimerHndlRef.current = setInterval(
() =>
secondsSet((s) => {
const v = s - 1;
if (v > 0) return v;
ClearTimer(TimerHndlRef);
return 0;
}),
1000,
);
};
const onChange = (e) => secondsSet(parseInt(e.target.value, 10));
useEffect(() => {
return () => {
if (!TimerHndlRef.current) return;
ClearTimer(TimerHndlRef);
};
}, []);
const mLeft = Math.floor(seconds / 60);
const sLeft = seconds - mLeft * 60;
const mDisp = mLeft < 10 ? `0${mLeft}` : mLeft;
const sDisp = sLeft < 10 ? `0${sLeft}` : sLeft;
return (
<div>
<p>
<input type="number" value={seconds} onChange={onChange} /> = {mDisp}m {" "}
{sDisp}s
</p>
<button onClick={onClick}>Test</button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Ответ №2:
С каждым щелчком мыши вы объявляете, что вычитается минута:
setMinutes(minutes - 1);
Если вы хотите, чтобы таймер был установлен только один раз, вы можете проверить, был ли он уже установлен, и если да, прервите функцию handleClick . Объявление let для таймера будет доступно только в этом блоке кода (для каждого запуска). Поэтому, когда произойдет еще один щелчок, у вас не будет доступа к таймеру. Используйте «this.interval» (область действия функции) или «var interval» (глобальная / оконная область), и тогда вы сможете проверить в верхней части функции handleClick, установлен ли таймер.
if (this.interval) return;
OR
if (interval) return;