-1

What I trying to achieve is, making a countdown to target day from now. inside of componentDidMount() :

nowT = moment(new Date()).format("X"); // => 1603551057 (2020-10-24)
targetDay = moment(result.data.created_at).add('30', 'days').format("X"); // => 1606143175 (2020-11-23)
diffTime = targetDay - nowT; // => 2592000
remain = moment.duration(diffTime, 'milliseconds'); // => {milliseconds: 0, seconds: 11, minutes: 43, hours: 0, days: 0, …}

let intervalId = setInterval(this.countdown(remain), 1000);
this.setState({
  counter: intervalId
});

First, I get now and targetday and calculate difference then send remaining to interval. here is countdown function:

countdown = (r) => {
  let remain = moment.duration(r - 1000, 'milliseconds');
  this.setState({
    currentCount: remain.days() + ':' + remain.hours() + ":" + remain.minutes() + ":" + remain.seconds()
  });
  console.log(remain.days() + ':' + remain.hours() + ":" + remain.minutes() + ":" + remain.seconds()); // => 0:0:43:11
}

Problem is it return wrong countdown 0:0:43:11 also it not update in render, just show this static countdown, not dynamic. what I have done wrong?

Jack The Baker
  • 1,781
  • 1
  • 20
  • 51
  • Duplicate of [Why does the setInterval callback execute only once?](https://stackoverflow.com/questions/10182714/why-does-the-setinterval-callback-execute-only-once) – Guy Incognito Oct 24 '20 at 15:20
  • Also even after fixing the interval, it's always called with the same parameter. You need to move all calculations into the `coundown` function. – Guy Incognito Oct 24 '20 at 15:21
  • You are returning the value of `this.countdown()` instead of passing the function reference of `this.countdown` – Samuel Hulla Oct 24 '20 at 15:27
  • @GuyIncognito nope, I moved all calculations into it, no success – Jack The Baker Oct 24 '20 at 15:35
  • That was just to fix the most obvious errors. I don't get why you calculate everything manually when you could just use Moment to get the result directly. – Guy Incognito Oct 24 '20 at 15:39
  • @GuyIncognito can you show me how can I do this via moment directly? *(because maybe I don't know momentjs too much, I just started to working with it)* – Jack The Baker Oct 24 '20 at 15:42

2 Answers2

1

Actually there is no need to calculate duration, once you get difference between then and now you can get what you want:

this.interval = setInterval(() => {
  nowT = moment();
  targetDay = moment(result.data.created_at).add('30', 'days');
  diffTime = moment(targetDay - nowT);
  timeObj = {
    count_days: diffTime.format('D');
    count_hours: diffTime.format('HH');
    count_minutes: diffTime.format('mm');
    count_seconds: diffTime.format('ss');
  }
}, 1000);

Now you can use setState to get values in render

Pedram
  • 15,766
  • 10
  • 44
  • 73
0

You are invoking the function this.countdown() which returns a value directly, instead of passing the function reference where you'd want to pass the argument.

If I were to literally interpret your code, what you're doing right now is:

// pseudo-code, serves only as example
setInterval(void, 1000)

when what you'd want to be doing is

// pseudo-code - serves only as example
setInterval(this.countdown, 1000)
// this is fine as long as we don't have to pass arguments ^

essentially in order to do this, you need to pass the function as a callback with the argument

setInterval(() => this.countdown(remain), 1000)

As a final note, don't forget to clearInterval() in componentWillUnmount() otherwise you might get a memory leak in your application.

Samuel Hulla
  • 6,617
  • 7
  • 36
  • 70
  • yes, I uesed `clearInterval` already. I used `setInterval(() => this.countdown(remain), 1000)` but still return wrong countdown. – Jack The Baker Oct 24 '20 at 15:40
  • likely because you put it in `componentDidMount()`. You need to be more specific than just 'wrong countdown'. It depends on what you're trying to achieve – Samuel Hulla Oct 25 '20 at 08:15