自动计数器显示意外行为

问题描述 投票:0回答:1

我有两个代码,如下所示。

[第一个是显示当前时间的时钟,每秒更新一次。它完美地工作!

第二个是非常相似的代码,但是它没有显示当前时间,而是一个每秒递增的计数器。

这是我们可以看到意外行为的地方,因为在最初的几秒钟之内就可以了,但是从第二个4或5开始(实际上可能是从第一个第二个秒开始发生,但是从第四,第五个第二个可见)。显示所有先前的值(秒)的速度非常快...并且当我们达到约10秒时,甚至看不到这些值。

请注意,如果我放弃了“ setInterval”函数,并且手动增加了单击按钮的值,它将按预期工作(我们在屏幕上只能看到增加的值)。

可能会发生什么?我是新来的反应者,感谢您的帮助;)

代码1:

import React, { useState } from "react";

function App() {
    let time = new Date().toLocaleTimeString();
    let [now, changeTime] = useState(time);

    function getCurrentTime() {

        let innerTime = new Date().toLocaleTimeString();
        changeTime(innerTime);
    }

    setInterval(getCurrentTime, 1000);


    return (
        <div className="container">
            <h1>{now}</h1>
            <button onClick={getCurrentTime}>Get Time</button>
        </div>
    );
}

export default App;

代码2:

import React, { useState } from "react";

function App() {
    let time = 0;
    let [now, changeTime] = useState(0);

    function getCurrentTime() {

        let innerTime = now;
        changeTime(innerTime+1);
    }

    setInterval(getCurrentTime, 1000);


    return (
        <div className="container">
            <h1>{now}</h1>
            <button onClick={getCurrentTime}>Get Time</button>
        </div>
    );
}

export default App;

index.js如下所示非常简单:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";


const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);
javascript reactjs react-hooks settimeout
1个回答
0
投票

问题:通过无条件设置间隔,将在每个渲染周期实例化该间隔,并且不会清除先前的间隔。

function App() {
    let time = 0;
    let [now, changeTime] = useState(0);

    function getCurrentTime() {

        let innerTime = now;
        changeTime(innerTime+1);
    }

    setInterval(getCurrentTime, 1000); // <-- Creates a new interval each render cycle!


    return (
        <div className="container">
            <h1>{now}</h1>
            <button onClick={getCurrentTime}>Get Time</button>
        </div>
    );
}

一个可能的解决方案:如果您只是想要一个自动计数器,那么仅需要状态和设置/清除计时器的效果就可以了:

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    // Use functional state update since next state depends on previous
    const timerID = setInterval(() => setCount(c => c + 1), 1000);
    // return interval cleanup function
    return () => clearInterval(timerID);
  }, []) // Empty dependency array to invoke effect once when component mounted

  return (
    <div className="container">
      <h1>{count}</h1>
    </div>
  );
}

Edit dry-leaf-f4in8

© www.soinside.com 2019 - 2024. All rights reserved.