反应状态未在 setInterval 内更新

时间:2021-01-19 22:19:28

标签: reactjs

我正在尝试通过一些简单的项目来学习 React,但似乎无法理解以下代码,因此希望得到解释。

这个来自简单倒计时函数的片段运行良好;但是,当我 console.log 时,setTime 似乎正确更新了 'seconds' 的值,但是当我在 console.log(time) 之后立即给我原始值 3 时。这是为什么?

额外问题 - 当函数 startCountdown 被调用时,我的 JSX 中出现的正确时间值会出现延迟,我认为这归因于变量“seconds”被填充和 setInterval 函数的开始,所以我不倒计时没有顺利和准确的开始。有没有办法解决这个问题?

const [ time, setTime ] = useState(3);
const [ clockActive, setClockActive ] = useState(false);

  
  function startCountdown() {
    let seconds = time * 60;
    setClockActive(true);
    let interval = setInterval(() => {
      setTime(seconds--);
      console.log(seconds); // Returns 179
      console.log(time); // Returns 3
        if(seconds < 0 ) {
        clearInterval(interval);
      }
    }, 1000)
  };

1 个答案:

答案 0 :(得分:0)

更新: 您在函数中没有看到正确值的原因是 setState 发生的方式(setTime)。当您调用 setState 时,它​​会批量调用并在后台需要时执行它们。所以你不能调用 setState 然后立即期望能够在函数内部使用它的值。

你可以把console.log从函数中取出,放到render方法中,你会看到正确的值。

或者你可以像这样试试useEffect。

//这意味着无论何时使用 setTime 并且组件更新,打印时间的当前值。仅在时间变化时执行此操作。

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

每次 setState 时,您都在重新渲染组件,这会导致对状态的破坏。因此,在 setInterval 中的每一秒,您都在重新渲染组件并在您已经运行的组件之上重新启动它。要解决此问题,您需要使用 useEffect 并传入您正在使用的状态变量。我在这里为你做了一个例子:

https://codesandbox.io/s/jolly-keller-qfwmx?file=/src/clock.js

import React, { useState, useEffect } from "react";
const Clock = (props) => {
  const [time, setTime] = useState(3);
  const [clockActive, setClockActive] = useState(false);

  useEffect(() => {
    let seconds = 60;

    setClockActive(true);
    const interval = setInterval(() => {
      setTime((time) => time - 1);
    }, 1000);

    if (time <= 0) {
      setClockActive(false);
      clearInterval(interval);
    }
    return () => {
      setClockActive(false);
      clearInterval(interval);
    };
  }, [time, clockActive]);

  return (
    <>
      {`Clock is currently ${clockActive === true ? "Active" : "Not Active"}`}
      <br />
      {`Time is ${time}`}
    </>
  );
};
export default Clock;