如何在Reactjs钩子内创建计时器?

bmp9r5qi  于 2023-02-08  发布在  React
关注(0)|答案(1)|浏览(119)

我是上周开始的React!)
我的第一个项目是创建一个计时器,它具有复位功能和秒计数功能。
重置函数工作得很好,但是计时器不是。哪种方法是最好的?它应该根据setTimeout()函数在变量'second'上增加+1s。
有可能在钩子上创建一个循环吗?我试着用下面的代码做,但是页面向下了,我想这是因为代码创建了无限循环;

const [hour, setHour] = useState(4)
    const [minute, setMinute] = useState(8)
    const [second, setSecond] = useState(12)

    // methods
    const setTime = (value: string) => {

        if (value === 'reset'){
            setHour(0);
            setMinute(0);
            setSecond(0);
        } 
    }

    const startTime = () => {
        while (second < 60){
            setTimeout(() => {
                setSecond(second + 1);
            }, 1000);
        }
    };

    <div className="d-flex justify-content-center">
         <MainButton 
             variantButton="outline-danger"
             textButton="RESET"
             functionButton={() => setTime('reset')}
     />
         <MainButton 
             variantButton="outline-success"
             textButton="START"
             functionButton={() => startTime()}
          /> 
     </div>
3htmauhk

3htmauhk1#

欢迎来到React!你非常接近了。setTimeoutsetInterval非常相似,因此你可以简单地使用setInterval。不需要while()循环!看看这个工作沙箱,我在其中创建了一个简单的React钩子,你可以在App.js中使用它
https://codesandbox.io/s/recursing-hooks-jc6w3v
代码陷入无限循环的原因是startTime()函数具有stale props。具体来说,second变量在本例中始终为0,因为当您在组件挂载时定义startTime()时,second为0。该函数不跟踪它的增量。
要解决此问题,请不要:
setSecond(second + 1);
尝试使用:
setSecond((s) => s += 1);
编辑 * 有很多关于React Stale Props的好文章,这里有一篇很有帮助:https://css-tricks.com/dealing-with-stale-props-and-states-in-reacts-functional-components/
编辑**有关确切问题的其他内联示例:

    • 我会做两个改变:**

1.在while()循环中使用setInterval而不是setTimeout。
1.创建一个处理定时器逻辑的useTimer钩子。

    • 应用程序js**
import "./styles.css";
import useTimer from "./useTimer";

export default function App() {
  const [setTime, startTime, stopTime, hour, minute, second] = useTimer();
  return (
    <div>
      <div className="d-flex justify-content-center">
        <button onClick={() => setTime("reset")}>RESET</button>
        <button onClick={startTime}>START</button>
        <button onClick={stopTime}>STOP</button>
      </div>
      <br />
      <div>
        Hour: {hour} <br />
        Minute: {minute} <br />
        Second: {second} <br />
      </div>
    </div>
  );
}
    • 使用计时器. js**
import { useState } from "react";

const useTimer = () => {
  const [hour, setHour] = useState(4);
  const [minute, setMinute] = useState(8);
  const [second, setSecond] = useState(12);
  const [timer, setTimer] = useState();

  // methods
  const clearTimer = () => clearInterval(timer);

  const setTime = (value) => {
    if (value === "reset") {
      setHour(0);
      setMinute(0);
      setSecond(0);
    }
  };

  const startTime = () => {
    if (timer) clearTimer();
    const newInterval = setInterval(() => {
      setSecond((s) => (s += 1));
    }, 1000);
    setTimer(newInterval);
  };

  const stopTime = () => clearTimer();

  return [setTime, startTime, stopTime, hour, minute, second];
};

export default useTimer;

相关问题