Vue 3 watch doesn’t work if I watch a destructured prop

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:

  1. Object (if the value is object), which is also reactive
  2. Value (integer for example) which cannot be reactive by itself

And destructuring is just value assigment:

const  { modelValue } = props 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) => {

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) enter image description here

link to the docs rule

So what you can do instead is use destructuring in the watch like so:

watch(() => {
  const { modelValue } = props;