Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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)
    })
}
like image 931
Liga Avatar asked Nov 20 '20 08:11

Liga


2 Answers

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

...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

like image 88
Michal Levý Avatar answered Oct 16 '22 13:10

Michal Levý


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;
  console.log(modelValue);
});
like image 22
Adam Orłowski Avatar answered Oct 16 '22 15:10

Adam Orłowski