React timer application

Posted on

Problem

I am writing a simple count down timer in React:

index.js

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import bootstrap from "bootstrap/dist/css/bootstrap.css";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

App.js:

import React, { useEffect, useState } from "react";

const App = () => {
  const oneSec = 1000;
  const [secCount, setSecCount] = useState(60);
  const [minCount, setMinCount] = useState(60);
  const [hrCount, setHrCount] = useState(24);

  useEffect(() => {
    const timer;    //<= here is my problem.
    if (secCount > 0) {
      timer = setInterval(() => {
        setSecCount(secCount - 1);
      }, oneSec);
    }
    if (secCount === 0 && minCount > 0) {
      timer = setInterval(() => {
        setSecCount(60);
      }, oneSec);
    }
    return () => clearInterval(timer);
  }, [secCount]);

  useEffect(() => {
    const timer =
      minCount > 0 &&
      setInterval(() => {
        setMinCount(minCount - 1);
      }, 60 * oneSec);
    return () => clearInterval(timer);
  }, [minCount]);

  return (
    <div>
      {minCount}:{secCount}
    </div>
  );
};

export default App;

I am having a hard time with my useEffect hooks. The first useEffect hook is supposed to update the second field, the logic is simply:

  • if secCount is bigger than 0, continue to countdown every second
  • if secCount is zero and minCount is bigger than 0, reset secCount to 60 and continue to countdown.

But since there are two branches in my first useEffect hook, I need to declare the timer variable and reassign it later. Can I get away with declaring it as let timer? A const variable does not allow me to change its value.

Solution

let vs const is fundamentally an ES6+ issue:

  • const
    Creates a constant whose scope can be either global or local to the block in which it is declared. An initializer for a constant is required. You must specify its value in the same statement in which it’s declared.
// wrong
const timer;
// Uncaught SyntaxError: Missing initializer in const declaration

// right
const timer = 60;
function do_something() {
  console.log(bar); // undefined
  console.log(foo); // ReferenceError
  var bar = 1;
  let foo = 2;
};

With that said, change the declaration to let timer;

// Within the first `useEffect`
useEffect(() => {
     let timer; // change this
     if (secCount > 0) {
       timer = setInterval(() => {setSecCount(secCount - 1)}, oneSec);
     }
     if (secCount === 0 && minCount > 0) {
       timer = setInterval(() => {setSecCount(60)}, oneSec);
     }
     return () => clearInterval(timer);
   }, [secCount]);
```

Leave a Reply

Your email address will not be published. Required fields are marked *