About props #14329
Replies: 2 comments 1 reply
-
|
Hey, I had the same confusion before so let me explain what I learned. When you destructure props like this: const { foo } = defineProps(["foo"])you basically extract the value at that moment. Its not reactive anymore, just a plain value. Thats why watch() cant detect changes. But watchEffect works different - it tracks whatever you access inside it while running. So when you use What you can do: Use getter function in watch: const { foo } = defineProps(["foo"])
watch(() => foo, (newVal) => {
console.log(newVal)
})Or dont destructure and use props directly: const props = defineProps(["foo"])
watch(() => props.foo, (newVal) => {
console.log(newVal)
})Or use toRefs if you really want destructuring: const props = defineProps(["foo"])
const { foo } = toRefs(props)
watch(foo, () => { ... }) // works nowBasically destructuring = copying value = losing reactivity. Hope this clears it up! |
Beta Was this translation helpful? Give feedback.
-
|
Props destructuring is a distraction here. You're essentially correct, that it compiles To be a bit more explicit, consider this code: const props = defineProps(['foo'])
watch(props.foo, () => {
console.log('changed')
})As you noted, this won't work. Here's a Playground showing that: As well as not triggering the watcher, you may also notice that Vue logs a warning. When we write Contrast that with what happens when you pass a ref. Say we have something like this: const r = ref(1)
watch(r, () => {...})In this case, the 'expression' for the first argument is just Now consider this case, similar to the earlier example but with a function wrapper around const props = defineProps(['foo'])
watch(() => props.foo, () => {
console.log('changed')
})This will work correctly: The key thing here is that we're passing the wrapper function to In general, Vue's dependency tracking relies on where properties are read. You can think of this as a dot operator, Going back to the earlier example with a ref called core/packages/reactivity/src/watch.ts Lines 153 to 154 in aa9af1d While this can sometimes be difficult to follow at first, one 'simple rule' that many of us use to spot mistakes quickly is 'dots should be inside functions'. This is only a guide, it sometimes won't apply, but it comes from the idea that reading properties needs to happen inside reactive effects. So consider these examples: watch(a, ...) // 1
watch(() => a, ...) // 2
watch(a.b, ...) // 3
watch(() => a.b, ...) // 4
Props destructuring is an awkward edge case in this regard, but so long as you know that Likewise, even if you aren't using props destructuring, you get something similar when you write something like |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
When I was learning how to use a ref object as a prop,I couldn't understand why
I know it will compile to
But I can't understand why prop.foo can't detected by watch()
AI told me it will auto unpack ref data,so prop.foo is just normal object
But I have learnt watchEffect() detect releative data by call it's getter or setter,if prop.foo is just normal object,it doesn't have getter or setter,so what causes this
Because it's difficult to read all source code about this part for me,so I came to there for help
Thanks
Beta Was this translation helpful? Give feedback.
All reactions