1

我正在关注useStateuseRef钩子的初学者教程,尝试在 react 中实现一个简单的计时器。

我正在使用interval变量来存储值setInterval()

单击开始按钮后,我可以正确地控制台记录间隔的值。但是,单击停止按钮时,interval.current控制台记录为undefined. 因此stopTimer()没有按预期运行。

为什么在 startTimer 中明确设置(并记录在那里)时,interval.current 打印未定义?我在这里想念什么?

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.log(interval.current, " :in start");
  }

  const stopTimer = (interval) => {
    console.log("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 ":in start" in stop: 未定义

谢谢

4

2 回答 2

2

我相信这是因为你传递了一个名为intervalto的较低范围变量stopTimer,但是当你调用时stopTimer你没有传递参数,所以当你访问它时它是未定义的。

您可能指的是interval您已定义为,ref因此您只需访问它而不传递intervalstopTimer,试试这个:

  const stopTimer = () => {
    console.log("in stop: ", interval.current);
    clearInterval(interval.current);
  }
于 2020-12-25T00:11:03.207 回答
0

考虑到您的代码在做什么,我认为interval应该是状态变量而不是参考。也就是说,你应该使用

const [interval, setInterval] = useState(null);

代替const interval = useRef(null);

Refs 用于链接到 DOM 元素(例如,您希望在单击按钮时引用的表单元素)。只有当一个 ref 变量正确地引用了一个 DOM 元素时,它们的current属性才被定义。

于 2020-12-25T00:06:16.970 回答