繁体   English   中英

SetInterval 仅第一次运行

[英]SetInterval only run for first time

我学习 javascript,反应,我试图从 10 数到 0,但不知何故计时器只运行到 9,我认为 setInterval 运行每 n 次我们设置(n 可以是 1000 毫秒,2000 毫秒......)

这是代码

import "./styles.css";
import React, { useState } from "react";
export default function App() {
  const [time, setTime] = useState(10);

  const startCountDown = () => {
    const countdown = setInterval(() => {
      setTime(time - 1);
    }, 1000);
    if (time === 0) {
      clearInterval(countdown);
    }
  };

  return (
    <div>
      <button
        onClick={() => {
          startCountDown();
        }}
      >
        Start countdown
      </button>
      <div>{time}</div>
    </div>
  );
}

这是代码: https://codesandbox.io/s/class-component-ujc9s?file=/src/App.tsx:0-506

请解释一下,我很困惑,谢谢

time是每次组件渲染时从 state 读取的值(这是传递给useState的默认值)。

单击时,您使用 function 调用setInterval ,该 function 在上次渲染后的time关闭

从那时起,每次渲染组件时,它都会从 state 中读取一个新的time值。

间隔仍然与原始变量一起使用,它仍然是10


如果您传入回调,State 函数将为您提供 state 的当前值。 所以使用它而不是封闭的变量。

setTime(currentTime => currentTime - 1);

只需在 setState function 中使用回调,因为否则反应正在使用旧的时间值:

import "./styles.css";
import React, { useState } from "react";
export default function App() {
  const [time, setTime] = useState(10);

  const startCountDown = () => {
    const countdown = setInterval(() => {
      setTime((prevTime)=>prevTime - 1);
    }, 1000);
    if (time === 0) {
      clearInterval(countdown);
    }
  };

  return (
    <div>
      <button
        onClick={() => {
          startCountDown();
        }}
      >
        Start countdown
      </button>
      <div>{time}</div>
    </div>
  );
}

编辑:您可以将间隔标识符存储在 useRef 中,因为 useRef 通过重新渲染持续存在并且不会导致另一个重新渲染,然后检查useEffect中的time和依赖时间

import "./styles.css";
import React, { useEffect, useRef, useState } from "react";
export default function App() {
  const [time, setTime] = useState(10);
  const interval = useRef(0);
  const startCountDown = () => {
    interval.current = setInterval(() => {
      setTime((prevTime) => prevTime - 1);
    }, 1000);
  };
  useEffect(() => {
    if (time === 0) {
      clearInterval(interval.current);
    }
  }, [time]);

  return (
    <div>
      <button
        onClick={() => {
          startCountDown();
        }}
      >
        Start countdown
      </button>
      <div>{time}</div>
    </div>
  );
}

工作沙箱: https://codesandbox.io/s/class-component-forked-lgiyj?file=/src/App.tsx:0-613

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM