vuejs / vue

This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core

Home Page:http://v2.vuejs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`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 shallowRefs 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