Stopping a Timer
Some things that a component starts go on by themselves. An interval from setInterval() runs again and again until something stops it with clearInterval(), as you know from the JavaScript course. When a component starts one, the component has to stop it too, when it's unmounted. Here's a banner that shows another of the café's specials every three seconds:
<script setup>
import { onMounted, onUnmounted, ref } from "vue";
const specials = ["Carrot Cake", "Cheesecake", "Mint Tea"];
const index = ref(0);
let timer;
onMounted(() => {
timer = setInterval(() => {
index.value = (index.value + 1) % specials.length;
}, 3000);
});
onUnmounted(() => {
clearInterval(timer);
});
</script>
<template>
<p>Try our {{ specials[index] }}!</p>
</template>%, the remainder, takes index back to 0 after the last special. And notice that:
timeris declared outside both hooks, withlet, so that both can use it:onMountedsaves the interval's id in it, andonUnmountedstops that interval.- The interval starts in
onMounted. At the top of<script setup>, it would work too, but inonMountedit starts when the component is on the page, and the two hooks read as a pair: what one starts, the other stops.
What if onUnmounted were missing? An interval knows nothing about components. When Vue removes the banner from the page, the interval keeps running for as long as the page is open, and keeps changing a ref that nothing shows. Each time the banner is shown again, a new component starts one more interval. You won't see that on the page, but you'll see it in the console, and that's what this exercise does.
The same goes for a setTimeout() that hasn't run yet, or a listener added with window.addEventListener(): what a component starts, onUnmounted stops.
A typical mistake: const timer = setInterval(…) inside onMounted. That constant exists only in the function of onMounted, so onUnmounted can't stop the interval.
Instructions
- 1
In
Timer.vue, start an interval inonMounted: every 1000 milliseconds, it increasessecondsby 1 and prints the time in the console withconsole.log(`Waiting: ${seconds.value} s`);. - 2
Click
Hide the timerand watch the console: the timer is gone, but the lines keep coming. ClickShow the timer: now the times of two intervals take turns in the console. Fix it: declarelet timer;aboveonMounted, save the interval's id in it, and stop the interval inonUnmountedwithclearInterval(timer).