为什么在我的 React 应用程序中使用 useEffect 和 setInterval 时会出现对象错误?

Why do I get an object error when using useEffect and setInterval in my React app?

我正在使用 React 构建一个带有 start/stop 按钮的计数器。我的功能组件中的 codepen 不断出现对象错误。我已将其缩小到 useEffect 中的 setInterval 行(codepen 中的第 32 行),但我无法弄清楚它有什么问题。

代码笔:https://codepen.io/sirstevekim/pen/zYROyxj

const App = () => {
  const [time, setTime] = React.useState(0);
  const [isRunning, setIsRunning] = React.useState(false);
  
  const counter = () => setTime(time + 1);
  
  React.useEffect(() => {
    const interval = null;
  
    if (isRunning === false) {
      interval = setInterval(counter, 1000);
    } else {
      clearInterval(interval);
    }
    return () => {clearInterval(interval)};
  }, [isRunning]);
  
  const handleStartStop = () => {
    setIsRunning(!isRunning);
  }
  
  const handleReset = () => {
    setIsRunning(false);
    setTime(0);
  }
  
  return (
    <div className="app">
      <Timer time={time} />
      <ControlButtons
        handleStartStop={handleStartStop}
        handleReset={handleReset}
      />
    </div>
  );
}

有几个问题需要更正,

  1. 您的计数器应该使用回调函数,否则它不会由于关闭问题而更新(它总是看到 0 并向其添加 1)。
const counter = () => setTime((prevTime) => prevTime + 1);
  1. 间隔应该是 let 而不是 const 因为你重新分配了它。
let interval = null;

工作演示

const Timer = (props) => {
  return <div className="timer">{props.time}</div>;
};

const ControlButtons = (props) => {
  return (
    <div>
      <button className="start-stop" onClick={props.handleStartStop}>
        Start/Pause
      </button>
      <button className="reset" onClick={props.handleReset}>
        Reset
      </button>
    </div>
  );
};

const App = () => {
  const [time, setTime] = React.useState(0);
  const [isRunning, setIsRunning] = React.useState(false);

  const counter = () => setTime((prevTime) => prevTime + 1);

  React.useEffect(() => {
    let interval = null;

    if (isRunning === false) {
      interval = setInterval(counter, 1000);
    } else {
      clearInterval(interval);
    }
    return () => {
      clearInterval(interval);
    };
  }, [isRunning]);

  const handleStartStop = () => {
    setIsRunning(!isRunning);
  };

  const handleReset = () => {
    setIsRunning(false);
    setTime(0);
  };

  return (
    <div className="app">
      <Timer time={time} />
      <ControlButtons
        handleStartStop={handleStartStop}
        handleReset={handleReset}
      />
    </div>
  );
};

ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>