JAVASCRIPT
Mastering Reactive Side Effects with Vue 3's watchEffect
Discover Vue 3's watchEffect for automatically tracking reactive dependencies and running side effects immediately, simplifying data synchronization and cleanup.
<template>
<div>
<input v-model="searchText" placeholder="Search...">
<p>Current search text: {{ searchText }}</p>
<p>Search results (simulated): {{ searchResults }}</p>
</div>
</template>
<script setup>
import { ref, watchEffect, onUnmounted } from 'vue';
const searchText = ref('');
const searchResults = ref('No search yet');
let searchTimeout = null;
// watchEffect will run immediately and re-run whenever searchText changes
watchEffect((onCleanup) => {
if (searchText.value.length > 2) {
// Simulate an API call with a debounce
searchTimeout = setTimeout(() => {
searchResults.value = `Results for "${searchText.value}"`;
console.log(`Performing search for: ${searchText.value}`);
}, 500);
} else {
searchResults.value = 'Type more than 2 characters to search.';
clearTimeout(searchTimeout); // Clear any pending search
}
// onCleanup callback runs when the effect is re-run or component is unmounted
onCleanup(() => {
console.log('Cleaning up previous search effect...');
clearTimeout(searchTimeout);
});
}, {
// Optional: Specify `flush: 'post'` to run after DOM updates, or `sync` for synchronous. Default is 'pre'.
// flush: 'post'
});
// Ensure cleanup happens if the component is unmounted before any watchEffect cleanup
onUnmounted(() => {
clearTimeout(searchTimeout);
});
</script>
How it works: `watchEffect` in Vue 3 is a powerful reactive primitive that automatically tracks the reactive dependencies accessed during its synchronous execution and re-runs the effect whenever those dependencies change. Unlike `watch`, it runs immediately on setup and doesn't require explicit source arguments. It provides an `onCleanup` function within its callback, which is useful for cleaning up side effects (like clearing timers or cancelling network requests) before the effect is re-executed or the component is unmounted. This example demonstrates a debounced search functionality.