react-countdown icon indicating copy to clipboard operation
react-countdown copied to clipboard

onComplete not called, when countdown have pass time

Open mfarchana opened this issue 3 years ago • 13 comments

image

When the time has expired, I try to open the page. Supposedly when the time expires then the status will change automatically, but oncomplete is not called

mfarchana avatar Jan 01 '22 08:01 mfarchana

Hi, this sandbox seems to be working as expected https://codesandbox.io/s/cranky-pare-2k5g8?file=/index.js:0-257. Could you eventually share some of your code to create a reproducible example?

ndresx avatar Jan 01 '22 13:01 ndresx

For example date={Date.now() - 3000} is show 00:00:00:00 not Completed.

mfarchana avatar Jan 01 '22 13:01 mfarchana

Ah, yes. You would have to provide a custom renderer like in this example https://codesandbox.io/s/sad-zhukovsky-hs7hc to display something else than the remaining time.

ndresx avatar Jan 01 '22 14:01 ndresx

How to prevent re-rendering with custom renderer ? So, I'll implement countdown to table, each row has time. When time is over, it will hit API once. In my case, its re-render twice after page loading. Therefore API call twice (duplicate data).

But when I set in onComplete its success, only send once.

mfarchana avatar Jan 01 '22 15:01 mfarchana

I'm not exactly sure what you are trying to achieve, but it sounds like that you'd have to store some state somewhere in your app, eventually the date prop of each countdown to prevent it from restarting or similar (if that's the issue).

I could probably help you more if you create a small example.

ndresx avatar Jan 01 '22 17:01 ndresx

Sorry for late response, please check my problem https://codesandbox.io/s/nice-liskov-8isml Refresh and see console log

mfarchana avatar Jan 02 '22 01:01 mfarchana

I see, thank you. While I think this can be improved (I've noted it down), I'd suggest you use the onComplete callback instead for this specific purpose because you shouldn't run an API request within a render function anyway.

Is there anything that prevents you from doing that?

ndresx avatar Jan 02 '22 01:01 ndresx

Please check my update https://codesandbox.io/s/nice-liskov-8isml, onComplete not triggered when time has over on data 1

mfarchana avatar Jan 02 '22 01:01 mfarchana

Ok, yes, that's sadly not happening right now in this case.

Would you expect it to trigger? Asking in general, maybe it makes more sense to trigger it consistently, even though the countdown might already be completed when initiated. I could also add a second argument to onComplete that would tell whether the countdown transitioned into the completed state or not. What do you think?

ndresx avatar Jan 02 '22 02:01 ndresx

Great idea, I'm waiting for your update. Thank you 👍

mfarchana avatar Jan 02 '22 03:01 mfarchana

@ndresx I think i'm having a similar issue, though can open a new if it doesn't overlap. sometimes the onComplete function doesn't run for me, I have a function that sets the date to Date.now() and pauses the timer so it shows 00:00:00, and 90% of the time it works as expected, but 10% of times the funtion isn't called, and the timer simply restarts. then when that reaches 0 the onComplete does run.

I haven't been able to reliably reproduce the issue as it seems to happen randomly, so unfortnunately cannot vreate a codeSandbox for this

EllipticElysium avatar Apr 05 '22 06:04 EllipticElysium

I was having the same issue as @EllipticElysium, and I even put up a PR to suggest an improvement for this. At its essence, I think the issue is that the onComplete callback is not invoked if the date prop has passed before the initialization of the Countdown component.

An alternative solution to this problem could be to pass a function to the onMount property and check whether it is completed there. E.g

const handleMount = (timeDelta: CountdownTimeDelta) => {
  if (timeDelta.completed) {
    onComplete();
  }
}

return <Countdown date={date} onMount={handleMount} onComplete={onComplete} />;

bendikjohansen avatar May 08 '22 14:05 bendikjohansen

A temporary solution to workaround prevents re-render when hit API, use delay / setTimeout in react

useEffect(() => { try { setTimeout(() => { //HIT API HERE }, 2000); } catch (err) { console.error(err); } }, []);

mfarchana avatar May 20 '22 07:05 mfarchana