状态更改未显示在控制台日志中

时间:2021-05-18 19:00:23

标签: reactjs state

我正在构建一个简单的计时器应用程序,并使用钩子跟踪状态中经过的时间。我知道我正在正确设置状态,因为它每隔一秒就会显示在应用程序中。但是,当我控制台日志 elapsedTime 时,它会重复记录初始状态(在本例中为 0):

const Timer = () => {
  const [elapsedTime, setElapsedTime] = React.useState(0);
  const [totalTime, setTotalTime] = React.useState(0);

  const handleStart = () => {
    const startTime = Date.now();
    setInterval(() => {
      const et = Math.floor((Date.now() - startTime) / 1000);
      setElapsedTime(et);
      console.log(elapsedTime);
    }, 1000);
  };

  const handleStop = () => {
    clearInterval();
  };

  return (
    <div className='container'>
      <div className='timer'>
        <div className='title'></div>
        <div className='time'>{elapsedTime}</div>
        <button onClick={handleStart}>Start</button>
        <button onClick={handleStop}>Stop</button>
      </div>
    </div>
  );
};

ReactDOM.render(<Timer />, document.getElementById("root"));
<div id="root"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

为什么我在第 9 行调用的 console.log 中没有反映我的状态变化?

3 个答案:

答案 0 :(得分:2)

setState 是异步的,你不会看到函数作用域的变化

如果您想在放置 console.log 的地方查看新值,您只能执行 console.log(et);

您也可以使用useEffect在控制台中查看变量的变化

useEffect(() => {
  console.log("elapsedTime", elapsedTime);
}, [elapsedTime]);

答案 1 :(得分:1)

由于 javascript clojure,第 9 行的 elapsedTime 将始终引用它在创建函数时的值。

答案 2 :(得分:0)

<块引用>

您将如何停止计时器?

您必须引用您正在创建的计时器,以便您可以停止它。调用 setInverval 会返回这样的引用(唯一 ID)。

然后,您必须确保在任何时间点都只运行一个计时器。

借用 Marc Charpentier 的回答,您的代码的工作版本可能如下所示:

const Timer = () => {
  const [elapsedTime, setElapsedTime] = React.useState(0);
  const [totalTime, setTotalTime] = React.useState(0);
  const [timerId, setTimerId] = React.useState();

  React.useEffect(() => {
    console.log("elapsedTime", elapsedTime);
  }, [elapsedTime]);

  const handleStart = () => {
    const startTime = Date.now();
    if (timerId === undefined) { // make sure that a timer is not already running
      setTimerId(
        setInterval(() => {
          const et = Math.floor((Date.now() - startTime) / 1000);
          setElapsedTime(et);
        }, 1000)
      );
    }
  };

  const handleStop = () => {
    clearInterval(timerId);
    setTimerId(undefined);
  };

  return (
    <div className='container'>
      <div className='timer'>
        <div className='title'></div>
        <div className='time'>{elapsedTime}</div>
        <button onClick={handleStart}>Start</button>
        <button onClick={handleStop}>Stop</button>
      </div>
    </div>
  );
};

ReactDOM.render(<Timer />, document.getElementById("root"));
<div id="root"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

相关问题