Farid Huseynov
Farid Huseynov

Reputation: 159

Timer not running inside the React Component

I'm working on the simple timer app in the React. Below is the code of what I have.

import React from "react"

const timer = (props) => {
 let time = 25;
 let processStatus = props.timerProcessStatus; // it comes as true
 if(processStatus === true) {
    setTimeout(() => {
        console.log(proccessStatus);
        countDown();
    }, 500)
 }

 function countDown(){
    time=time-1;
    console.log(time);
 }

 return (
    <div>
        <p id={props.statusId}>{props.timerStatus}</p>
        <p id={props.timerStatusId}>{time}:00</p>
    </div>
 )
}
export default timer;

And here is the snapshot of what I get in the browser enter image description here

As it shows, the time variable changed to 24 (although I would expect it to decrease to 23 second time), it doesn't re-renders in the paragraph, where the content is {time}:00

Upvotes: 0

Views: 1133

Answers (4)

Nilesh Patel
Nilesh Patel

Reputation: 3317

  1. setInterval is the method to be used to run code/function in specific interval..
  2. any async task should be run in useEffect

function App(){
 const [time,setTime]=React.useState(25)
  let processStatus = true; // it comes as true

  function countDown() {
    // time = time - 1;
    setTime(prevTime=>prevTime-1)
    // console.log(time);
  }
  let timer;
  React.useEffect(() => {
    if (processStatus === true) {
      timer = setInterval(() => {
        countDown();
      }, 500);
    }
    return ()=>{
      clearInterval(timer)
    }
  }, []);
  return (
    <div className="App">
      <h1>Hello CodeSandbox-{time}</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

ReactDOM.render(<App/>,document.getElementById("root"))
<script src= "https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src= "https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>

<div id="root"></div>

Upvotes: 1

azdeviz
azdeviz

Reputation: 758

use the following code for the timer .

import React,{UseEffect,UseState} from 'react';

const timer=(props)=>{

const [time, setTime] = useState(25);

UseEffect(()=>{
let processStatus = props.timerProcessStatus;
 // it comes as true 
if(processStatus === true) { setTimeout(() => { console.log(proccessStatus); countDown(); }, 500) }
}, [])

function countDown(){ 
setTime(time--); 
}
// other code 

Upvotes: 1

Yousaf
Yousaf

Reputation: 29314

Incrementing a local variable won't cause a re-render of your component.

You need to put time in the state of your component. Updating the state will cause a re-render of the component which will then update the value of time in the DOM.

import React, {useState} from "react"

const timer = (props) => {
   const [time, setTime] = useState(25);  // local state 
 
   ...

   function countDown(){
      setTime(prevTime => prevTime + 1);  // update the state
   }

   ...
}

Every time countDown function will be called, it will update the state, causing a re-render of the component.

I suggest you to read React - State and Lifecycle to understand why you need time as a state of the component.

Upvotes: 3

KnowYourElements
KnowYourElements

Reputation: 412

My guess is that it tries to create the time variable each time

so I would suggest to put the time variable in its parent component then just use

 function countDown(){
    let newTime = time;
    props.setTime(newTime - 1);
    console.log(newTime - 1);
 }


Upvotes: 0

Related Questions