Automati c counter показывает неожиданное поведение - PullRequest
0 голосов
/ 29 апреля 2020

У меня есть две части кода, как показано ниже.

Первые часы показывают текущее время, обновляемое каждую секунду. Работает отлично!

Второй код очень похож, но вместо того, чтобы показывать текущее время, это счетчик, который увеличивает себя каждую секунду.

Здесь мы можем увидеть неожиданное поведение, потому что оно хорошо в течение первых нескольких секунд, но со вторых 4 или 5 (на самом деле это может произойти с первой секунды, но видно с четвертой, пятой секунды ) он начинает показывать все предыдущие значения (секунды) довольно быстро ... и когда мы достигаем примерно 10 se c, невозможно даже увидеть значения.

Обратите внимание, что если я избавлюсь от функция "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;

Индекс. 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
);

1 Ответ

0 голосов
/ 30 апреля 2020

Проблема: Не устанавливая интервал без условий, он создается каждый цикл рендеринга, а предыдущий интервал не очищается.

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

...