Slots props are undefined while using both props destructuring and useSlots()
Version
3.2.13
Reproduction link
Steps to reproduce
Parent.vue
<template>
<Demo v-slot="{ item }">
<div>{{ item }}</div>
</Demo>
</template>
Child.vue
<template>
<slot :item="111" />
</template>
<script setup>
import { useSlots } from 'vue'
console.log(useSlots().default())
</script>
What is expected?
Prop "item" should be usable (displays "111")
What is actually happening?
Props are undefined. Error Cannot destructure property 'item' of 'undefined' as it is undefined.
I have DataTable
component where columns are defined in slot as DataTableColumn
component for easy usage, like that:
<DataTable
:data="someData"
v-slot="slotProps"
>
<DataTableColumn name="id">
<span class="xxxx">{{ slotProps.item.id }}</span>
</DataTableColumn>
<DataTableColumn name="email">
{{ slotProps.item.email }} {{ slotProps.item.something }} etc
</DataTableColumn>
</DataTable>
I'm getting columns list thanks to useSlots().default()
if (slots.default) {
columns.value = slots.default()
.filter((node) => node.props)
.flatMap((node) => node.props)
}
current item (row) is passed as slot props to parent
<tr
v-for="(item, key) in data"
:key="key"
>
<slot :item="item" />
</tr>
and it works great, I was using similar approach multiple times, also in vue 2.
Problem is that for some reason I cannot use object destructuring on slot props, like that:
<DataTable
:data="someData"
v-slot="{ item }"
>
<DataTableColumn name="id">
<span class="xxxx">{{ item.id }}</span>
</DataTableColumn>
<DataTableColumn name="email">
{{ item.email }} {{ item.something }} etc
</DataTableColumn>
</DataTable>
In console I'm getting
TypeError: Cannot destructure property 'item' of 'undefined' as it is undefined.
It's caused only by using default()
in code. Why it is undefined while firing default()
, even in onMounted()
?
So why is default()
working alone, and { item }
is working alone, but not both combined? For me it's bug, but maybe I'm wrong and someone will clarify this.
You need to pass the relevant information to the slot, in this case item
:
useSlots().default({ item })