Svelte5 introduces effect
function. On the documentation page there is an example of a simple counter with an option to increase / decrease the interval using setInterval
function.
Here is the code:
<script>
let elapsed = $state(0);
let interval = $state(1000);
$effect(() => {
const id = setInterval(()=>{
elapsed += 1;
}, interval)
});
</script>
<button onclick={() => interval /= 2}>speed up</button>
<button onclick={() => interval *= 2}>slow down</button>
<p>elapsed: {elapsed}</p>
When we click the speed up
button the interval gets updated and the new counter runs fast.
However, when we click the slow down
button, the interval gets updated but the speed doesn't reduce.
The explanation given on the doc page is as follows:
That’s because we’re not clearing out the old intervals when the effect updates. We can fix that by returning a cleanup function:
Now the question is that when we are not clearing out the old intervals then the speed up
should also not work.
Why do we have a case where speed up
is working but slow down
is not working when both lead to change of state i.e. interval
value.
You are just adding additional intervals, so you end up with overlapping updates. Adding more such updates can only ever increase the update speed.
If you click twice you have three separate update cycles running at the same time:
The removal of existing update intervals is a prerequisite for slowing it down.