Navigating Vue.js Watch: Insights for Experienced Developers
Hey Everyone,
This article covers the reasons, and situations in which you should utilize Vue.js watch. Whether you’re a seasoned Vue.js developer or have some prior experience with Vue.js, this post serves as a valuable resource.
Table of content
Overview 🚀
With Vue.js Watch, we can create custom reactions to changes in reactive state, ensuring our app’s user interface is up-to-date and dynamic. Since Vue.js encourages a declarative approach to UI development, the watch option aligns more with an imperative programming style. Therefore, it’s advisable to use watchers cautiously or applying them only when the requirements align with their primary purpose
The Role of Watch in Vue.js 🎥
The primary role of the watch option in Vue.js is to monitor changes in reactive state or data properties and trigger a callback to execute side effects or asynchronous actions in response to those changes. However, the term “side effects” can be ambiguous, and not all side effects are welcomed to be run in watch. It’s essential to clarify what kinds of side effects are recommended and what should be avoided.
When to Use Vue.js Watch? 🕵️♂️
Asynchronous Operations 🔄
The watch feature offers versatility in monitoring different types of data changes. It can be applied to a reactive state, prop, route, specific reactive state, or changes in nested properties and perform side effects or actions in response to those changes. However, the term “side effects” is broad and covers a range of actions, including simple tasks like assigning a variable or displaying a notification. Yet, it’s not welcomed to use watches for such actions. So performing asynchronous tasks, such as making API calls or fetching data from a server, should be the primary use case for watch.
Example Scenario 🧐
Suppose we encounter a situation requiring the use of the watch option to initiate API calls then best would be to create a dedicated function for handling data/assigning some variables and data assigning must be done in a separate function.
For instance, in a user reporting dashboard, there is a parent component called UserReportDashboard responsible for managing user selections, and a child component named UserReportDetails responsible for displaying detailed reports for the selected user. The UserReportDetails component receives the userId prop and watches for changes in the selected userId using the watch option. When the userId changes, it triggers the fetchUserReport method.
watch(props.userId, async newUserId => {
const response = await fetchUserReport(newUserId);
processUsersData(response);
});
const processUsersData = () => {
// process users
};
Here we watch for changes in a prop userId. When the property changes, instead of directly mutating or assigning fetchUserReport response to some variable in watch, we call the function to do it indirectly. This way, it would be in a more predictable and efficient manner.
When to Avoid Vue.js Watch? ⚠️
Recommended by LinkedIn
Avoid Assigning Values Inside Watch 🚫
In certain parent-child communication scenarios, deriving local state from received props is common. While using a watch to update these derived properties or assign values to other variables when a prop changes is possible, it might not align with the primary idea of working with reactive state in Vue.js and could lead to losing the single source of truth.
Vue.js offers computed properties tailored for this purpose, presenting a more efficient and readable alternative.
Example Scenario 🤖
Take, for example, a PageItem component receiving a prop named someValue from its parent PageList. By utilizing computed properties to derive local data from this prop maintains a single source of truth. With computed properties’ getter/setter, changes in someValue ensure the parent always retains the most up-to-date prop value
The ideal solution in such scenarios depends on the specific context, example scenario could be as follows.
// Avoid doing it
watch(
() => props.someValue,
newValue => {
localState.value = newValue;
}
)
}
For this scenario we have better alternative
const derivedValue = computed({
get() {
return props.someValue;
},
set(newValue) {
emit("change", newValue)
},
});
Using computed properties ensures maintaining a single source of truth and enhances code readability as well.
Avoid Directly Mutating Other Data Properties ❌
We should not directly mutate or assign values to other data properties within a watch handler:
watch((oldValue, newValue)=> {
// Avoid direct mutation of other properties
otherProperty.value = newVal;
});
Avoid Heavy Logic/Control Flow in Watch Handlers 🤯
It’s better to create separate functions for better readability and maintainability:
watch((oldValue, newValue)=> {
// do not put complex logic/control flow directly inside watch
processData(newVal);
});
Summary 🌟
Thank you for reading! These practices are commonly followed in our day-to-day coding when working with Vue.js and its watch feature. However, it’s important to note that every project or team may have its own coding guidelines, so usage should be adapted accordingly.
Feel free to share your approaches and experiences in using Vue.js watch. Your feedback on this post is also welcome!