Я пытаюсь создать страницу секундомера в React, которая позволяет пользователю устанавливать время, в которое он / она хочет, чтобы секундомер остановился. Мой код выглядит следующим образом:
const Timer = () => {
const [status, setStatus] = useState(0);
// Not started = 0
// started = 1
// stopped = 2
const [time, setTime] = useState({ s: 0, m: 0, h: 0 }); // The time values of the stopwatch
const [interv, setInterv] = useState(); // An interval will be set into this "interv" constance
const [stopwatch, setStopwatch] = useState({
m: 0,
h: 0,
}); // The time a user designates for the stopwatch to stop by itself
const start = () => {
run();
setStatus(1);
setInterv(setInterval(run, 1000));
};
var updatedS = time.s,
updatedM = time.m,
updatedH = time.h;
const run = () => {
updatedS++;
if (updatedS === 60) {
updatedM++;
updatedS = 0;
}
if (updatedM === 60) {
updatedH++;
updatedM = 0;
}
if (updatedM == stopwatch.m && updatedH == stopwatch.h) {
stop();
} // the code that stops the stopwatch automatically in accordance to the time a user had set
return setTime({
s: updatedS,
m: updatedM,
h: updatedH,
});
};
const stop = () => {
clearInterval(interv);
setStatus(2);
};
const reset = () => {
clearInterval(interv);
setStatus(0);
setStopwatch({
m: 0,
h: 0,
});
setTime({ s: 0, m: 0, h: 0 });
};
const resume = () => start();
return (
<div className="main-section">
<div className="clock-holder">
<div className="stopwatch">
<DisplayComponent time={time} />
<form>
<Grid container spacing={4} className="">
<Grid item xs={3}>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel id="Stopwatch-Hour-label">Hour</InputLabel>
<Select
labelId="Stopwatch-Hour-label"
id="Stopwatch-Hour"
value={stopwatch.h}
onChange={(event) => {
setStopwatch({ ...stopwatch, h: event.target.value });
}}
label="Hour"
disabled={status === 0 ? false : true}
>
<MenuItem value={0}>
<em>0</em>
</MenuItem>
<MenuItem value={1}>1</MenuItem>
<MenuItem value={2}>2</MenuItem>
<MenuItem value={3}>3</MenuItem>
<MenuItem value={4}>4</MenuItem>
<MenuItem value={5}>5</MenuItem>
<MenuItem value={6}>6</MenuItem>
<MenuItem value={7}>7</MenuItem>
<MenuItem value={8}>8</MenuItem>
<MenuItem value={9}>9</MenuItem>
<MenuItem value={10}>10</MenuItem>
<MenuItem value={11}>11</MenuItem>
<MenuItem value={12}>12</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={3}>
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel id="Stopwatch-Minute-label">Minute</InputLabel>
<Select
labelId="Stopwatch-Minute-label"
id="Stopwatch-Minute"
value={stopwatch.m}
onChange={(event) => {
setStopwatch({ ...stopwatch, m: event.target.value });
}}
label="Minute"
disabled={status === 0 ? false : true}
>
<MenuItem value={0}>
<em>0</em>
</MenuItem>
<MenuItem value={5}>5</MenuItem>
<MenuItem value={10}>10</MenuItem>
<MenuItem value={15}>15</MenuItem>
<MenuItem value={20}>20</MenuItem>
<MenuItem value={25}>25</MenuItem>
<MenuItem value={30}>30</MenuItem>
<MenuItem value={35}>35</MenuItem>
<MenuItem value={40}>40</MenuItem>
<MenuItem value={45}>45</MenuItem>
<MenuItem value={50}>50</MenuItem>
<MenuItem value={55}>55</MenuItem>
</Select>
</FormControl>
</Grid>
</Grid>
</form>
<BtnComponent
status={status}
resume={resume}
reset={reset}
stop={stop}
start={start}
/>
</div>
</div>
</div>
);
};
export default Timer;
Пока секундомер работает, когда я нажимаю кнопку остановки или кнопку сброса вручную, секундомер останавливается, не вызывая никаких проблем. Однако, если бы я дождался его остановки в установленное мной время, значение состояния изменится на 2, что означает, что таймер остановился, но значения времени на секундомере продолжают увеличиваться.
Я думаю Причина, по которой это не сработает так, как задумано, заключается в том, что React Hooks являются асинхронными c, но я понятия не имею, как я могу это исправить.
В этом случае, как я могу заставить таймер останавливаться самостоятельно в назначенное время при использовании хуков (в данном случае - useState) ??
Прямо сейчас действительно нуждается в помощи ..