Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

146
Views
onClick decreases the number with each click rather than starting the timer

So I'm building a meditation app in React. To start out simple I gave it a 25 minute countdown.

I want the countdown to start when the button is clicked. However, when I wrap the setInterval in the handleClick() function the seconds go down per click rather than triggering the countdown once.

Any help is appreciated, thanks in advance.

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


function Timer() {
  const [minutes, setMinutes] = useState(25);
  const [seconds, setSeconds] = useState(0);

  function handleClick() {
    console.log('Clicked');
    let interval = setInterval(() => {
      clearInterval(interval);
      if (seconds === 0) {
        if (minutes !== 0) {
          setSeconds(59);
          setMinutes(minutes - 1);
      } else {
        setSeconds(seconds - 1);
      }
    }, 1000)
  }

  const timerMinutes = minutes < 10 ? `0${minutes}`: minutes;
  const timerSeconds = seconds < 10 ? `0${seconds}` : seconds;

  return (
    <>
      <div className="grey-box">
        <div className="number-box">
          <h2 className="timer-text">{timerMinutes}:{timerSeconds}</h2>
        </div>
        <div className="buttons-container">
          <button className="timer-button" onClick={handleClick}>
            <img 
              className="play" 
              src="https://img.icons8.com/ios-glyphs/90/ffffff/play--v1.png" 
            />
          </button>
        </div>
      </div>
    </>
    );
  }

export default Timer;
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

You are declaring with each click that a minute is subtracted:

setMinutes(minutes - 1);

If you want the timer to only be set once, you can check to see if it has already been set, and if so, abort the handleClick function. A let declaration for the timer will only be available in that block of code (per run). So when another click happens, you won't have access to the timer. Use "this.interval" (function scope) or "var interval" (global/window scope) and then you will be able to check at the top of the handleClick function if the timer is already set.

if (this.interval) return;

OR

if (interval) return;

about 4 years ago · Juan Pablo Isaza Report

0

You're creating the Timer in a much more complicated manner. I made a sample that can cover this use case along with some edge cases.

Codesandbox link

import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";

function ClearTimer(TimerHndlRef) {
    clearInterval(TimerHndlRef.current);
    TimerHndlRef.current = null;
}
function App() {
    const TimerHndlRef = useRef();
    const [seconds, secondsSet] = useState(5);
    const onClick = () => {
        if (TimerHndlRef.current) {
            ClearTimer(TimerHndlRef);
            return;
        }
        TimerHndlRef.current = setInterval(
            () =>
                secondsSet((s) => {
                    const v = s - 1;
                    if (v > 0) return v;
                    ClearTimer(TimerHndlRef);
                    return 0;
                }),
            1000,
        );
    };
    const onChange = (e) => secondsSet(parseInt(e.target.value, 10));
    useEffect(() => {
        return () => {
            if (!TimerHndlRef.current) return;
            ClearTimer(TimerHndlRef);
        };
    }, []);
    const mLeft = Math.floor(seconds / 60);
    const sLeft = seconds - mLeft * 60;
    const mDisp = mLeft < 10 ? `0${mLeft}` : mLeft;
    const sDisp = sLeft < 10 ? `0${sLeft}` : sLeft;
    return (
        <div>
            <p>
                <input type="number" value={seconds} onChange={onChange} /> = {mDisp}m +{" "}
                {sDisp}s
            </p>
            <button onClick={onClick}>Test</button>
        </div>
    );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!