Skip to content

Dupliucate ref in template with v-if checking for the ref leads to a recursion error #12246

Open
@Markussss

Description

@Markussss

Vue version

3.5.12

Link to minimal reproduction

https://play.vuejs.org/#eNp9kVFLwzAUhf9KuC9TmB1uPo1uoLIHfVBRHwNSurua2SYhSWuh9L97b8pmH0ZfQjjnO+Hc3A7urU2aGmENqc+dskF4DLXdSq0qa1wQnXB4EL04OFOJGaEzqaXOjfZBBKRjw8DVtdTpYniBsmnAypZZQLoLkXqbaaY2EjgiYRuTt5QgZ5JZjpm9akRzo0YMy2LosYrIghgusBg1gDkET40PqkiO3mgatmNYQm4qq0p0rzYomkjCWkSHvawsze9z1IKrcX7S82/Mfy7oR9+yJuHNoUfXoISzFzJXIPVle/fxgi3dz2Zl9nVJ9IT5jt6UNXccsIda76n2iIttn+LKlC4+/a4NqP1pKC7KZB95CbTGx4nR/+uukruYk7qnX/xq0PGb9IFkJMsl9H/6uL08

Steps to reproduce

Use a ref on at least two elements, outside of a v-for, in order to create a referenced element. The last element in the DOM will be the referenced element. Add a v-if check on another element for the ref-element.

This is the same code as in the minimal reproduction:

<script setup>
import { ref } from 'vue'

const test = ref()
</script>
<template>
  <span ref="test">test 1</span>
  <span ref="test">test 2</span>
  <div v-if="test">
    test 3
  </div>
</template>

What is expected?

I was expecting for the code to work without any error messages, or give an error message that is possible to understand.

What is actually happening?

Uncaught (in promise): Maximum recursive updates exceeded in component . This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.

System Info

No response

Any additional comments?

It is not clear why this leads to a recursion error, and that makes it hard to debug when you accidentally end up in this situation.

I think a good solution to this problem would be to throw another exception than a Recursion here. Perhaps something like "Duplicate referenced element outside of v-for"? Or perhaps it could "just work", like it does if you wrap the referenced element in a computed, like this:

<script setup>
import { computed, ref } from 'vue'

const test = ref()
const test2 = computed(() => test.value)
</script>
<template>
  <span ref="test">test 1</span>
  <span ref="test">test 2</span>
  <div v-if="test2">
    test 3
  </div>
</template>

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions