Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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 –

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading