Home > Net >  React Class Component - This.Set.State
React Class Component - This.Set.State

Time:06-30

I'm trying to complete this countdown timer using a class component in REACT. I believe I'm just missing "this.Setstate" adding . Can you please review and let me know where that would be added in this component? Thanks in advance! (I've edited the code by adding "this.Setstate", however, I'm receiving an error message that it's not a function). Just to add more detail, I'm trying to have the countdown timer start when the screen loads. It's not triggered by a button or anything.

import React,{Component} from "react";

class Countdown extends Component{
    constructor(props){
        super(props);
            this.state={
            days:30,
            hours:720,
            minutes:59,
            seconds:59
           }   
        }

        componentDidMount(){
            let countDownDate = new Date("Jul 30, 2022 11:00:00").getTime();
           
            /*Function myFunc runs every second*/

         
            let myfunc = setInterval(function() {
        
                let now = new Date().getTime();
                let timeleft = countDownDate - now;                  
             this.setState({
                    days: Math.floor(timeleft / (1000 * 60 * 60 * 24)),
                    hours : Math.floor((timeleft % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
                    minutes: Math.floor((timeleft % (1000 * 60 * 60)) / (1000 * 60)),
                    seconds: Math.floor((timeleft % (1000 * 60)) / 1000),
                         
                })
            } , 1000);  
            }
           

    
         render(){    
    return (
        <>
        <div>
        <p>{this.days}</p>
        <p>{this.hours}</p>
        <p>{this.minutes}</p>
        <p>{this.seconds}</p>
        </div>
        </>
        )
        }
    
}

export default Countdown;

CodePudding user response:

To save the values in the state, as you mentioned, you effectively need to add the this.setState method.

You are currently storing the date values into global values like this.days. This works but it doesn't re-render the component on change.

So what you need to do is replace the this.<DATE_VALUE> with something like this:

/*Breakdown the calculation*/
this.setState({
  days: YOUR_DAYS_VALUES,
  hours: YOUR_HOURS_VALUES,
  minutes: YOUR_MINUTES_VALUES,
  seconds: YOUR_SECONDS_VALUES,
})

Edit:

As @madQuestions commented, as this.setState is inside a setInterval function we need to bound it to the current class (this is not necessary with arrow functions). This happens because inside the setInterval scope we don't have a clue of the class values. That is why we need the binding.

You can check this comment post to understand better what is happening.

So your interval would look something like this:

let myfunc = setInterval(
  function () {
    let now = new Date().getTime();
    let timeleft = countDownDate - now;
    this.setState({
      days: Math.floor(timeleft / (1000 * 60 * 60 * 24)),
      hours: Math.floor(
        (timeleft % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
      ),
      minutes: Math.floor((timeleft % (1000 * 60 * 60)) / (1000 * 60)),
      seconds: Math.floor((timeleft % (1000 * 60)) / 1000)
    });
  }.bind(this), // we added the binding here
  1000
);

Additionally I was able to see in your code that you are still returning the this.<DATE_VALUE> in your JSX code. You have to change that to this.state.<DATE_VALUE> to get the state values.

  • Related