JAVASCRIPT
Efficient Reactive Side Effects with Vue 3's `watchEffect`
Discover `watchEffect` in Vue 3 for automatically re-running a side effect whenever its reactive dependencies change. It's a powerful alternative to `watch` for simpler, auto-tracking scenarios.
<template>
<div>
<h2>User Profile</h2>
<input type="text" v-model="firstName" placeholder="First Name" />
<input type="text" v-model="lastName" placeholder="Last Name" />
<p>Full Name: {{ fullName }}</p>
<p>Logs updated name in console (check console).</p>
</div>
</template>
<script setup>
import { ref, watchEffect, computed } from 'vue';
const firstName = ref('John');
const lastName = ref('Doe');
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
// watchEffect automatically tracks firstName and lastName
watchEffect(() => {
console.log(`User's full name changed to: ${firstName.value} ${lastName.value}`);
// This effect will re-run whenever firstName or lastName changes.
});
// Example with cleanup
const userId = ref(1);
watchEffect((onInvalidate) => {
console.log(`Fetching data for user ID: ${userId.value}`);
const abortController = new AbortController();
fetch(`https://jsonplaceholder.typicode.com/users/${userId.value}`, { signal: abortController.signal })
.then(response => response.json())
.then(data => console.log('Fetched user:', data.name))
.catch(error => {
if (error.name === 'AbortError') {
console.log('Fetch aborted for user ID:', userId.value);
} else {
console.error('Fetch error:', error);
}
});
// Cleanup logic for previous effect run
onInvalidate(() => {
abortController.abort();
console.log(`Cleanup: Aborting fetch for user ID: ${userId.value}`);
});
});
// You can change userId to see cleanup in action
// setTimeout(() => userId.value = 2, 2000);
</script>
How it works: `watchEffect` simplifies common reactive scenarios by automatically tracking any reactive state accessed within its callback, re-running the effect whenever that state changes. This makes it ideal for synchronizing state, logging, or performing cleanup operations without explicitly listing dependencies. The `onInvalidate` callback provided to `watchEffect` is crucial for cleaning up side effects (like pending API requests or timers) before the effect re-runs or the component unmounts, preventing memory leaks and race conditions.