What Causes This Warning?
This warning occurs when you try to use a reserved property name as a prop. Vue reserves certain property names for internal use, such as key, ref, $, and properties starting with _.
The Problem
<script setup>
// ❌ Using reserved prop names
defineProps({
key: String, // Reserved by Vue for list rendering
ref: String, // Reserved for template refs
$data: Object, // $ prefix is reserved
_internal: String // _ prefix is reserved
})
</script>
The Fix
Use Different Prop Names
<script setup>
// ✅ Use non-reserved names
defineProps({
itemKey: String, // Instead of 'key'
reference: String, // Instead of 'ref'
dataObject: Object, // Instead of '$data'
internal: String // Instead of '_internal'
})
</script>
Reserved Property Names
These names are reserved and cannot be used as props:
| Reserved Name | Why Reserved |
|---|---|
key | Used for list rendering (v-for) |
ref | Used for template refs |
$el | Instance property |
$data | Instance property |
$props | Instance property |
$attrs | Instance property |
$refs | Instance property |
$slots | Instance property |
$parent | Instance property |
$root | Instance property |
$emit | Instance method |
$watch | Instance method |
$forceUpdate | Instance method |
$nextTick | Instance method |
_* | Internal Vue properties |
Common Scenarios
List Item Component
<!-- ❌ Wrong - 'key' is reserved -->
<script setup>
defineProps({
key: String,
value: String
})
</script>
<!-- ✅ Correct -->
<script setup>
defineProps({
itemKey: String,
value: String
})
</script>
<!-- Parent usage -->
<template>
<ListItem
v-for="item in items"
:key="item.id"
:item-key="item.id"
:value="item.name"
/>
</template>
Reference Prop
<!-- ❌ Wrong -->
<script setup>
defineProps({
ref: Object // Reserved!
})
</script>
<!-- ✅ Correct -->
<script setup>
defineProps({
reference: Object,
// or
elementRef: Object,
// or
targetRef: Object
})
</script>
Data Object Prop
<!-- ❌ Wrong -->
<script setup>
defineProps({
$data: Object
})
</script>
<!-- ✅ Correct -->
<script setup>
defineProps({
data: Object,
// or
modelData: Object,
// or
formData: Object
})
</script>
Private/Internal Props
<!-- ❌ Wrong - _ prefix is reserved -->
<script setup>
defineProps({
_config: Object,
_internal: Boolean
})
</script>
<!-- ✅ Correct -->
<script setup>
defineProps({
config: Object,
isInternal: Boolean
// or use a different naming convention
})
</script>
When You Need Similar Names
<script setup>
// If you're wrapping a component that expects 'key'
// Use a different name and map it
const props = defineProps({
itemKey: String
})
// Use itemKey internally but pass as needed
</script>
<template>
<!-- Pass to native element or third-party component -->
<div :data-key="itemKey">
{{ itemKey }}
</div>
</template>
TypeScript Considerations
// Type definitions should also avoid reserved names
interface Props {
// ❌ These would conflict
// key: string
// ref: HTMLElement
// ✅ Use alternative names
itemKey: string
elementRef: HTMLElement
}
defineProps<Props>()
Quick Checklist
- Don’t use
keyorrefas prop names - Avoid
$prefix for prop names - Avoid
_prefix for prop names - Use descriptive alternatives like
itemKey,reference - Check Vue instance properties for other reserved names
- Update parent components when renaming props