Skip to content

noVueWatchAfterAwait (JavaScript)

Language JavaScript (and super languages)
biome.json
{
"linter": {
"rules": {
"nursery": {
"noVueWatchAfterAwait": "error"
}
}
}
}

Disallow creating Vue watchers after an await in setup().

A watcher created with watch() or watchEffect() belongs to the component whose setup() function is currently running, and Vue stops it when that component is removed from the page. When setup() pauses at an await, Vue stops tracking which component is being set up. A watcher created after that point doesn’t belong to any component, so it keeps running after the component is gone.

A watcher is allowed when the function it returns is stored or passed somewhere, for example const stop = watch(...), because that function can be called later to stop the watcher.

Code inside <script setup> isn’t checked, because Vue keeps track of the component across each await there.

<script>
import { watch } from "vue";
export default {
async setup() {
await fetchUser();
watch(source, () => {});
},
};
</script>
code-block.vue:7:5 lint/nursery/noVueWatchAfterAwait ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ This watcher is created after an await, so it keeps running after the component is removed.

5 │ async setup() {
6 │ await fetchUser();
> 7 │ watch(source, () => {});
│ ^^^^^^^^^^^^^^^^^^^^^^^
8 │ },
9 │ };

ℹ The setup() function pauses here. After this point, Vue no longer knows which component the watcher belongs to.

4 │ export default {
5 │ async setup() {
> 6 │ await fetchUser();
│ ^^^^^
7 │ watch(source, () => {});
8 │ },

ℹ Create the watcher before the first await in setup(), or store the function it returns and call that function to stop the watcher.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

<script>
import { watch } from "vue";
export default {
async setup() {
watch(source, () => {});
await fetchUser();
const stop = watch(source, () => {});
},
};
</script>