2
\$\begingroup\$

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.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Yes, you can. Also, instead of declaring it twice inside useEffect, declare timer outside the effect hook and re-assign inside useEffect when needed \$\endgroup\$ – Sunil Chaudhary Apr 23 '20 at 13:56
3
\$\begingroup\$

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]);
```
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.