【问题标题】:clearInterval not working if using setState React.js [duplicate]如果使用 setState React.js,clearInterval 不起作用 [重复]
【发布时间】:2021-04-29 04:09:41
【问题描述】:

我正在使用 React 构建一个倒数计时器并遇到了这个问题:如果 clearInterval 不更新组件,它会在 Cklick 上起作用。如果我在区间函数 clearInterval 中更新状态,则不再清除区间。我知道它与组件重新渲染有关?这是代码的相关部分。非常感谢您的建议:

const [sessionCount, setSessionCount] = useState(25);
const [timeLeft, setTimeLeft] = useState("25:00")

  
var timer ;
 
function startHandle() {
    let endTime = (sessionCount * 60000) + +new Date();
    timer = setInterval(function() {
        let diff = endTime - +new Date();
        const min = Math.floor(diff / 60000);
        const sec = Math.floor((diff / 1000) % 60);
        setTimeLeft(min + ":" + sec) //if this line is removed, then clearInterval works
    }, 1000)
};
function resetHandle() {
  setTimeLeft("25:00");
  clearInterval(timer);
};
<div id="time-display-container">
    <div id="timer-label">Session</div>
    <time id="time-left"></time>
    <button id="start_stop" onClick={startHandle}>start/stop</button>
    <button id="reset" onClick={resetHandle}>reset</button>
</div>

【问题讨论】:

  • 重新渲染时,timer 未保留其最后一个值。最好将其保存在 ref 中,使用 useRef 在重新渲染之间保持其值。
  • @Giovanni Esposito 谢谢,看来我不擅长回答已经提出的问题。我会尝试使用 ref 和 useEffect 来解决这个问题,以便更好地做出反应。
  • @Rohit Khanna 谢谢,我会尝试 useRef 和 useEffect

标签: reactjs use-state clearinterval


【解决方案1】:

将计时器移到 App 组件之外。

import React, { useState } from "react";

let timer;


export default function App() {
  const [sessionCount, setSessionCount] = useState(25);
  const [timeLeft, setTimeLeft] = useState("25:00");


  function startHandle() {
    let endTime = sessionCount * 60000 + +new Date();
    timer = setInterval(function () {
      let diff = endTime - +new Date();
      const min = Math.floor(diff / 60000);
      const sec = Math.floor((diff / 1000) % 60);
      setTimeLeft(min + ":" + sec); //if this line is removed, then clearInterval works
    }, 1000);
  }

  function resetHandle() {
    setTimeLeft("25:00");
    clearInterval(timer);
  }

  return (
    <div id="time-display-container">
      <div id="timer-label">Session</div>
      <time id="time-left" />
      {timeLeft}
      <button id="start_stop" onClick={startHandle}>
        start/stop
      </button>
      <button id="reset" onClick={resetHandle}>
        reset
      </button>
    </div>
  );
}

另外,您检查计时器值以防止设置多个设置间隔。 我猜想在 useEffect 中定义这个计时器并在其他状态更改中调用它们会更具反应性,但是上面的代码在codesandbox 中对我有用。

【讨论】:

    猜你喜欢
    • 2018-11-02
    • 2013-01-17
    • 1970-01-01
    • 2020-07-04
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    相关资源
    最近更新 更多