0

Im trying to do a Pomodoro Clock timer, which is basically two timers that alternate between. Thats all the code:

import React, { useState } from "react";

function Challenge20() {
    const [timer, setTimer] = useState('');
    let minutes = 0;
    let seconds = 0;
    const [workRest, setWorkRest] = useState('work');


function startTimer() {
    document.getElementById('start').style.display = 'none';
    minutes = document.getElementById('work').value - 1;
    seconds = 59;
    setInterval(reduceSeconds, 1000);
};

function reduceSeconds() {
    
    if (seconds < 10) {
        setTimer(minutes + ':' + '0' + seconds);
    }
    else {
        setTimer(minutes + ':' + seconds);
    }

    seconds -= 1;

    if (seconds < 1 && minutes > 0) {
        seconds = 59;
        minutes -= 1;
    }
    else if (seconds == 0  && minutes == 0){
        setWorkRest(workRest == 'work' ? 'rest' : 'work');
        minutes = document.getElementById(workRest == 'work' ? 'work' : 'rest').value;
    }
};

return (
    <>  
        <label>Work Minutes:</label>
        <input id='work' type='number' max='60'/>
        <br/>
        <label>Rest Minutes:</label>
        <input id='rest' type='number' max='60'/>
        <br/>
        <br/>
        <span id='timer'>{workRest} -&gt; {timer}</span>
        <button id='start' onClick={() => startTimer()}>Start!</button>
    </>
);
};

export default Challenge20;

The problem is in this part:

else if (seconds == 0  && minutes == 0){
            setWorkRest(workRest == 'work' ? 'rest' : 'work');
            minutes = document.getElementById(workRest == 'work' ? 'work' : 'rest').value;
        }

The setState is not changing from 'work' to 'rest', also tried to call a function to change the state, clearing interval and 2 separated if, nothing worked, what am I doing wrong?

Sasquatch
  • 87
  • 1
  • 2
  • 7
  • Why use DOM manipulation (`document.getElementById`) ? Why not just have the `value={stateVariable}` on your input fields? Maybe read https://stackoverflow.com/questions/44471370/controlled-vs-uncontrolled-components-in-react this answer and refactor a bit? – ᴓᴓᴓ Oct 22 '21 at 16:42
  • Im using `document.getElementById` because idk another way to change `minutes` from one input value to other one without it – Sasquatch Oct 22 '21 at 16:56
  • Why not just make it a state variable? – ᴓᴓᴓ Oct 22 '21 at 17:50
  • I can, but how can this solve my problem? – Sasquatch Oct 22 '21 at 18:14
  • Sorry, I completely misunderstood the problem, see if the answer I've added now makes sense.. – ᴓᴓᴓ Oct 22 '21 at 18:27

2 Answers2

0

I think this is what you're trying to achieve? The problem is that the timer keeps going. On the next iteration, it sets workRest back to its previous value. To solve this, I used clearInterval to stop iterating, and decremented seconds to display 00:00 on the timer. As such, I had to assign the interval creation to a variable we can pass into clearInterval.

import React, { useState } from "react";

function Challenge20() {
  const [timer, setTimer] = useState("");
  let minutes = 0;
  let seconds = 0;
  const [workRest, setWorkRest] = useState("work");
  let interval;
  function startTimer() {
    document.getElementById("start").style.display = "none";
    minutes = document.getElementById("work").value - 1;
    seconds = 59;
    interval = setInterval(reduceSeconds, 1);
  }

  function reduceSeconds() {
    if (seconds < 10) {
      setTimer(minutes + ":" + "0" + seconds);
    } else {
      setTimer(minutes + ":" + seconds);
    }

    seconds -= 1;

    if (seconds < 1 && minutes > 0) {
      seconds = 59;
      minutes -= 1;
    } else if (seconds == 0 && minutes == 0) {
      console.log();
      setWorkRest(workRest == "work" ? "rest" : "work");
      minutes = document.getElementById(workRest == "work" ? "work" : "rest")
        .value;
      clearInterval(interval);
      seconds -= 1;
    }
  }

  return (
    <>
      <label>Work Minutes:</label>
      <input id="work" type="number" max="60" />
      <br />
      <label>Rest Minutes:</label>
      <input id="rest" type="number" max="60" />
      <br />
      <br />
      <span id="timer">
        {workRest} -&gt; {timer}
      </span>
      <button id="start" onClick={() => startTimer()}>
        Start!
      </button>
    </>
  );
}
ᴓᴓᴓ
  • 1,178
  • 1
  • 7
  • 18
0

useState is not work inside the condition. For ex: you are set the state value in the if condition. State value not updated in condition.

Micro Kumar
  • 167
  • 1
  • 12