snippetjavascriptvueCritical
How to watch props change with Vue Composition API / Vue 3?
Viewed 0 times
withhowapicompositionwatchvuepropschange
Problem
While Vue Composition API RFC Reference site has many advanced use scenarios with the
Neither is it mentioned in Vue Composition API RFC's main page or vuejs/composition-api in Github.
I've created a Codesandbox to elaborate on this issue.
`
null value
Empty value
import { createComponent, watch } from "@vue/composition-api";
export default createComponent({
name: "MyInput",
props: {
selected: {
type: [String, Number],
required: true
}
},
setup(props) {
console.log("Setup props:", props);
watch((first, second) => {
console.log("Watch function called with args:", first, second);
// First arg function registerCleanup, second is undefined
});
// watch(props, (first, second) => {
// console.log("Watch props function called with args:", first, second);
// // Logs error:
// // Failed watching path: "[object Object]" Watcher only accepts simple
// // dot-delimited paths. For full control, use a function instead.
// })
watch(props.selected, (first, second) => {
console.log(
"Watch props.selected function called with args:",
first,
second
);
// Both props are undefined so it's just a bare callback func to be run
});
watch module, there are no examples of how to watch component props.Neither is it mentioned in Vue Composition API RFC's main page or vuejs/composition-api in Github.
I've created a Codesandbox to elaborate on this issue.
Prop watch demo with select input using v-model:
import { createComponent, onMounted, ref } from "@vue/composition-api";
import PropWatchDemo from "./components/PropWatchDemo.vue";
export default createComponent({
name: "App",
components: {
PropWatchDemo
},
setup: (props, context) => {
const testValue = ref("initial");
onMounted(() => {
setTimeout(() => {
console.log("Changing input prop value after 3s delay");
testValue.value = "changed";
// This value change does not trigger watchers?
}, 3000);
});
return {
testValue
};
}
});
`
null value
Empty value
import { createComponent, watch } from "@vue/composition-api";
export default createComponent({
name: "MyInput",
props: {
selected: {
type: [String, Number],
required: true
}
},
setup(props) {
console.log("Setup props:", props);
watch((first, second) => {
console.log("Watch function called with args:", first, second);
// First arg function registerCleanup, second is undefined
});
// watch(props, (first, second) => {
// console.log("Watch props function called with args:", first, second);
// // Logs error:
// // Failed watching path: "[object Object]" Watcher only accepts simple
// // dot-delimited paths. For full control, use a function instead.
// })
watch(props.selected, (first, second) => {
console.log(
"Watch props.selected function called with args:",
first,
second
);
// Both props are undefined so it's just a bare callback func to be run
});
Solution
If you take a look at
Your callback was only called once. The reason it was called at least once is because the new
So by accident you are doing the same thing Tony Tom suggested but with the wrong value. In both cases, it is not valid code when you are using TypeScript.
You can do this instead:
Here the 1st function is executed immediately by Vue to collect dependencies (to know what should trigger the callback) and 2nd function is the callback itself.
Other way would be to convert props object using
However, most of the time watching props is not needed. Simply use
watch typings here it makes it clear the first argument of watch could be an array, function or Refprops passed to the setup function are a reactive object (likely by readonly(reactive()), it's properties are getters. So what you are doing is passing the value of the getter as the 1st argument of watch, string "initial" in this case. Because Vue 2 $watch API is used under the hood (and same function exists in Vue 3), you are effectively trying to watch non-existent property with name "initial" on your component instance.Your callback was only called once. The reason it was called at least once is because the new
watch API is behaving like the current $watch with the immediate option (UPDATE 03/03/2021 - this was later changed and in release version of Vue 3, watch is lazy same way as it was in Vue 2)So by accident you are doing the same thing Tony Tom suggested but with the wrong value. In both cases, it is not valid code when you are using TypeScript.
You can do this instead:
watch(() => props.selected, (first, second) => {
console.log(
"Watch props.selected function called with args:",
first,
second
);
});
Here the 1st function is executed immediately by Vue to collect dependencies (to know what should trigger the callback) and 2nd function is the callback itself.
Other way would be to convert props object using
toRefs so it's properties would be of type Ref and you can pass them as the first argument of watch.However, most of the time watching props is not needed. Simply use
props.xxx directly in your template (or setup) and let Vue do the rest.Context
Stack Overflow Q#59125857, score: 260
Revisions (0)
No revisions yet.