Skip to content

toRef and computed don't behave the same when used with a getter function #13819

@ByScripts

Description

@ByScripts

Vue version

3.5.20

Link to minimal reproduction

https://play.vuejs.org/#eNqNUs1OwzAMfhUrl3ZSVcbgNAESoB3gAAg45lJat8tokypxYWjqu+Ok6zYkmDi18ffjz4k34rpt048OxVxcuNyqlsAhde2V1KppjSXYgMUyATLP/vOZUb5clCXmlEBumrYjLKCH0poGIjaKpJY6N9oRNF+Pbyu49Pp4A6qYQ1QaE0E/8Rxuc6cJ7UdWx/EELq9gIzUMopSLHbL0h0zqPoHZdDoN+qGHKk6ZFsJtXQ4MUlUwdSTOmDgm/osr9cGAW5LXmxrT2lRxdLvMdMUTx6HlJEp8gsFhwvr/qsccg8Fsb3BxMrwC3z8fCJu2zgj5BPCCOLp53gEmEkGOoVJV6coZzY8Z7lIK30fVaB9bUiyVYj7csseyujaf96FGtsNkrOdLzN9/qa/c2tekeLLo+N1Qih1Gma2QBnjx8oBr/t+BjSk6znwMfEYeq/MZB9pNpwuOfcALae/CSipdvbrFmlC7cSgf1DP7wJeCF/H2yOj7uGfpedDxbon+G4GTAmI=

Steps to reproduce

  1. Use this code
    import { ref, toRef, watchEffect, computed } from 'vue'
    
    const myObj = ref({ id: 'foo' })
    
    setInterval(() => {
      myObj.value = { id: 'foo' }
    }, 2000)
    
    const id1 = toRef(() => myObj.value.id)
    const id2 = computed(() => myObj.value.id)
    
    watchEffect(() => console.log('Changed (toRef)', id1.value))
    watchEffect(() => console.log('Changed (computed)', id2.value))
  2. Check the console for logs

What is expected?

Both watchEffect to be executed once.

Using toRef with a getter should create a computed (or at least have the same behavior as computed)

What is actually happening?

watchEffect using the value created with toRef triggers every time the source object is updated, even if the the getter produces the same result.

Using computed with a getter creates a ComputedRef, which triggers reactivity only when its result change.

Using toRef with a getter creates a Readonly<Ref>>, which triggers reactivity even if its result doesn't change.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions