What Causes This Warning?
This warning occurs when you call useTemplateRef() multiple times with the same key. Each template ref key should be unique and defined only once.
The Problem
<script setup>
import { useTemplateRef } from 'vue'
// ❌ Duplicate template ref keys
const inputRef = useTemplateRef('input')
const anotherInputRef = useTemplateRef('input') // Warning!
</script>
The Fix
Use Unique Keys
<script setup>
import { useTemplateRef } from 'vue'
// ✅ Unique keys for each ref
const usernameRef = useTemplateRef('username')
const emailRef = useTemplateRef('email')
const passwordRef = useTemplateRef('password')
</script>
<template>
<input ref="username" />
<input ref="email" />
<input ref="password" />
</template>
Single Declaration Per Key
<script setup>
import { useTemplateRef, onMounted } from 'vue'
// ✅ Declare once, use anywhere
const inputRef = useTemplateRef('input')
onMounted(() => {
inputRef.value?.focus()
})
function clearInput() {
if (inputRef.value) {
inputRef.value.value = ''
}
}
</script>
<template>
<input ref="input" />
<button @click="clearInput">Clear</button>
</template>
Common Scenarios
Accidental Duplication
<!-- ❌ Might happen with copy-paste -->
<script setup>
const ref1 = useTemplateRef('element')
// ... lots of code ...
const ref2 = useTemplateRef('element') // Forgot this exists!
</script>
<!-- ✅ Check for existing refs before adding -->
<script setup>
const elementRef = useTemplateRef('element')
// Use elementRef throughout
</script>
In Composables
// ❌ Composable called multiple times
export function useInput(key) {
const ref = useTemplateRef(key) // Duplicate if same key!
return ref
}
// Usage
const input1 = useInput('input') // OK
const input2 = useInput('input') // Warning!
// ✅ Pass ref from outside or use unique keys
export function useInput(inputRef) {
// Work with provided ref
return {
focus: () => inputRef.value?.focus(),
clear: () => {
if (inputRef.value) inputRef.value.value = ''
}
}
}
// Usage
const inputRef = useTemplateRef('input')
const { focus, clear } = useInput(inputRef)
Dynamic Refs
<script setup>
import { useTemplateRef, ref } from 'vue'
// ❌ Can't use useTemplateRef dynamically in loop
// items.forEach(item => useTemplateRef(item.id)) // Bad!
// ✅ Use ref array for lists
const itemRefs = ref([])
function setItemRef(el, index) {
itemRefs.value[index] = el
}
</script>
<template>
<div
v-for="(item, index) in items"
:key="item.id"
:ref="el => setItemRef(el, index)"
>
{{ item.name }}
</div>
</template>
Traditional ref() Alternative
<script setup>
import { ref } from 'vue'
// ✅ Traditional approach still works
const inputRef = ref(null)
</script>
<template>
<input ref="inputRef" />
</template>
useTemplateRef vs ref()
<script setup>
import { ref, useTemplateRef } from 'vue'
// Both approaches work:
// Approach 1: Traditional ref
const traditionalRef = ref(null)
// Approach 2: useTemplateRef (Vue 3.5+)
const templateRef = useTemplateRef('myElement')
</script>
<template>
<!-- Traditional: ref name matches variable name -->
<div ref="traditionalRef">Traditional</div>
<!-- useTemplateRef: ref name matches key parameter -->
<div ref="myElement">Template Ref</div>
</template>
Quick Checklist
- Use unique keys for each
useTemplateRef()call - Don’t duplicate
useTemplateRef()with same key - For lists, use callback refs with
ref()array - Traditional
ref()approach still works - Check existing refs before adding new ones