Take value from user and start countdown in react

I am making a countdown app using React JS and Tailwind CSS and currently the countdown is running on manual input from the useState hook but I want to take the input from the user and when the user clicks the submit button then I want to start the countdown.
Please could someone help me – I have been stuck on this for the last 2 hours! Thanks!

Here is the code:

App.js –

import React from 'react'
import CountDown from './components/CountDown'

const App = () => {
  return (
    <div>
      <CountDown/>
    </div>
  )
}

export default App

CountDown.js-

import React, { useState, useEffect, useRef } from 'react'

const CountDown = () => {
  const [count, setCount] = useState(10);
  let cntVal = useRef();

  const handleChange = e =>{
    setCount(e.target.value)
  }

  const handleSubmit = () =>{
    if(count < 0){
      alert("Count cannot be negative!");
      return;
    }
  }

  useEffect(() => {
    cntVal.current = setInterval(() => {
      setCount(prev => prev - 1)
    }, 1000)
    return () => clearInterval(cntVal.current)
  },[]);

  useEffect(() => {
    if(count === 0){
      clearInterval(cntVal.current);
      alert("END!")
    }
  })
  
  return (
    <div className='h-[100vh] w-full flex flex-col items-center justify-center'>
      <div className="border border-black p-12 items-center justify-center">
        <div className="flex justify-center">
          <p className='text-3xl font-bold'>Countdown App</p>
        </div>
        <div className="flex justify-center mt-10">
          <p className='font-semiboldld text-2xl'>{count}</p>
        </div>
        <div className="flex mt-10 mb-4 items-center justify-center">
          <label htmlFor="name" className='text-xl'>Enter a Number: </label>
          <input className='border border-black ml-2 p-2 rounded-lg text-xl' type="text" name="cntDown" ref={cntVal} id="cntDown" onChange={handleChange} />
        </div>
        <div className="flex justify-center">
          <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" onClick={handleSubmit}>
            Submit
          </button>
        </div>
      </div>
    </div>
  )
}

export default CountDown

>Solution :

You can start the countdown from the handleSubmit function:

const handleSubmit = () =>{
    if(count < 0){
      alert("Count cannot be negative!");
      return;
    }
    cntVal.current = setInterval(() => {
      setCount(prev => prev - 1)
    }, 1000)
  }

The only other change is in your ‘unmount’ logic, check if (cntVal.current) is set before calling clearInterval(cntVal.current);

const {  useState, useEffect, useRef } = React;

const CountDown = () => {
  const [count, setCount] = useState(10);
  let cntVal = useRef();

  const handleChange = e =>{
    setCount(e.target.value)
  }

  const handleSubmit = () =>{
    if(count < 0){
      alert("Count cannot be negative!");
      return;
    }
    cntVal.current = setInterval(() => {
      setCount(prev => prev - 1)
    }, 1000)
  }

  useEffect(() => {
    return () => {
        if (cntVal.current) {
            clearInterval(cntVal.current);
        }

    }
  },[]);

  useEffect(() => {
    if(count === 0){
      clearInterval(cntVal.current);
      alert("END!")
    }
  })
  
  return (
    <div className='h-[100vh] w-full flex flex-col items-center justify-center'>
      <div className="border border-black p-12 items-center justify-center">
        <div className="flex justify-center">
          <p className='text-3xl font-bold'>Countdown App</p>
        </div>
        <div className="flex justify-center mt-10">
          <p className='font-semiboldld text-2xl'>{count}</p>
        </div>
        <div className="flex mt-10 mb-4 items-center justify-center">
          <label htmlFor="name" className='text-xl'>Enter a Number: </label>
          <input className='border border-black ml-2 p-2 rounded-lg text-xl' type="text" name="cntDown" ref={cntVal} id="cntDown" onChange={handleChange} />
        </div>
        <div className="flex justify-center">
          <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" onClick={handleSubmit}>
            Submit
          </button>
        </div>
      </div>
    </div>
  )
}

ReactDOM.render(<CountDown />, document.getElementById("react"));

ReactDOM.render(<CountDown />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Leave a Reply