`triggerRef` does not trigger `watch`
undergroundwires opened this issue · comments
Expected behavior
Watching values of manually triggered references should execute the watch callback.
Reproduce
This test fails:
import { nextTick } from 'vue'
test('triggerRef with watch', async () => {
const a = shallowRef(1)
let aTriggered = false
watch(() => a.value, () => {
aTriggered = true
})
triggerRef(a)
await nextTick()
expect(aTriggered).toBe(true)
})
More information
Watching the ref
itself works fine. According to post by @LinusBorg in vuejs/core#1209 (comment), this is the expected design of Vue.
However, getting value
of the ref
does not work. So watch(() => a.value, ...)
won't work but, watch(a, ...)
work. The behavior should be the same and consistent for shallowRef
s where state tracking is disabled
watchEffect
works fine for these .value
calls. This is another undocumented inconsistency with watch
.
Official Vue docs state nothing about caching for watch
.
As noted in the following comments, the current behavior is expected: vuejs/core#1209 (comment)
@posva OP also opened this issue in the core repo, and there I noted that there is one weird thing: watch(aShallowRef, ...)
does trigger the watch. Normal refers, or getter functions, don't. So only when you watch a shallowRef directly, it will be triggered.
This seeems to be by design, but I question the wisdom of that design. See vuejs/core#9579 (comment)
Should we consider re-opening this issue here until we settled the raised question over in core?
Hi, sorry for the duplication, I got confused and opened two issues.
I'd appreciate at least there would be some documentation regarding this. I've updated my application to use watch(aShallowRef
to get this working for now.
A trivia: All of the major language models I asked for help including GPT 4.0 is confused about this behavior and expects watch(() => aShallowRef.value)
to be triggered, not only humans 🙂
I think having one is core is enough but I think current behavior makes more sense: when you pass a getter, if the returned value do not change, the watcher shouldn’t trigger