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

I'm building a counter with a start/stop button using React. I keep getting an object error on codepen in my functional component. I've narrowed it down to the setInterval line (line 32 in codepen) within useEffect, but I can't figure out what's wrong with it.

Codepen: 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>
  );
}


Solution 1:[1]

Few issues to be corrected,

  1. Your counter should be using a callback function otherwise it won't update due to a closure issue (it always sees 0 and adds 1 to it).
const counter = () => setTime((prevTime) => prevTime + 1);
  1. interval should be let instead of const since you reassign it.
let interval = null;

Working Demo

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>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Amila Senadheera