Не могу заставить секундомер остановиться в то время, которое я установил - PullRequest
1 голос
/ 05 августа 2020

Я пытаюсь создать страницу секундомера в 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) ??

Прямо сейчас действительно нуждается в помощи ..

...