scripter2021
scripter2021

Reputation: 391

Why does rerendering not effect counting with setTimeout?

I have a component with controlled inputs. This component is also a parent for a Timer component. The Timer component counts down from 20 to 0 using setTimeout. Right now the child component rerenders on every key stroke (and therefore the state change) in a parent component.

const Timer = () => {
    const [secondsLeft, setSecondsLeft] = useState(20);

    if (secondsLeft) { 
        setTimeout(() => setSecondsLeft(secondsLeft - 1), 1000);   
    }

    const displayTime = '00:' + String(secondsLeft).padStart(2, '0');

    if (secondsLeft > 0) { 
        return <span>Time left {displayTime}</span>;   
    }
    
    return <span>You're out of time!</span>;
};

My question is why the countdown timer works properly and it's interval is always exacly 1 second no matter how fast I type in a parent input element. Why rerendering does not affect the setTimeout?

Upvotes: 2

Views: 49

Answers (1)

4b0
4b0

Reputation: 22323

If you update 5 times in a second, you now have 5 timers that will call setSecondsLeft(secondsLeft - 1) for that second. Luckily only the first one triggers a rerender because the subsequent calls don't change the value.

Try using:

setSecondsLeft(secondsLeft  => secondsLeft - 1)

Note: answer provided by Thomas on comment section.

Upvotes: 1

Related Questions