I am trying to watch a prop in Vue 3 but it is strange that when I destructure it then the watcher doesn't work. But without destructuring it works as expected. What am I missing here?
P.S. I am using Vue 3 + Vite
This is not working
export default {
    props: {
        modelValue: {
            type: Boolean,
            default: false,
        },
    },
    setup({ modelValue }, context)
    {
        watch(() => modelValue, (newValue, oldValue) => {
            console.log(newValue)
        })
    },
}
But if I don’t destructure it then it works
setup(props, context) {
    watch(() => props.modelValue, (newValue, oldValue) => {
        console.log(newValue)
    })
}
props passed into setup is reactive object and all reactivity is tight to the proxy around the object itself.
If you take a value of the property of such object, you get either:
And destructuring is just value assigment:
const  { modelValue } = props
...is same as:
const modelValue = props.modelValue 
You can use toRefs as described in docs
export default {
    props: {
        modelValue: {
            type: Boolean,
            default: false,
        },
    },
    setup(props, context)
    {
        let { modelValue } = toRefs(props)
        watch(modelValue, (newValue, oldValue) => {
            console.log(newValue)
        })
    },
}
Now modelValue is ref so it can be passed as first argument of watch (no need to for a function) and in most places you must use modelValue.Value to get it's value
Destructuring the props will cause the value to lose reactivity. (vue/no-setup-props-destructure)

link to the docs rule
So what you can do instead is use destructuring in the watch like so:
watch(() => {
  const { modelValue } = props;
  console.log(modelValue);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With