The Problem
When you pass content through Vue slots, the slot content is compiled in the parent's scope. If the parent's reactive state changes, the slot content may not re-render because the reactivity context was lost during the slot projection.
Symptoms
- Parent state changes but slot content still shows old values
- Works with direct template binding but not through slots
- Scoped slots work but regular slots do not update
- Child component re-renders but slot content is stale
Real Error Scenario
```vue <!-- Parent.vue --> <template> <CardWrapper> <p>Count: {{ count }}</p> <!-- Does NOT update when count changes --> </CardWrapper> </template>
<script setup> const count = ref(0); setInterval(() => count.value++, 1000); </script>
<!-- CardWrapper.vue --> <template> <div class="card"> <slot></slot> <!-- Slot content is compiled once --> </div> </template> ```
Actually, in Vue 3, default slots DO re-render because the parent re-renders and the slot content is part of the parent's VNode tree. The issue typically arises with more complex scenarios.
Real Scenario: Reactivity Loss Through Dynamic Components
```vue <!-- Parent --> <template> <DynamicWrapper :component="currentComponent"> <template #header> <h1>{{ title }}</h1> <!-- May not update if wrapper caches --> </template> </DynamicWrapper> </template>
<script setup> const title = ref('Initial'); const currentComponent = shallowRef(ComponentA);
// Later: title.value = 'Updated'; // Slot may not re-render if wrapper cached its slots </script> ```
How to Fix It
Fix 1: Use Scoped Slots for Reactive Data
```vue <!-- CardWrapper.vue --> <template> <div class="card"> <slot :count="count" :title="title"></slot> </div> </template>
<script setup> const count = ref(0); const title = ref('Card Title'); </script>
<!-- Parent.vue --> <CardWrapper v-slot="{ count, title }"> <p>{{ title }}: {{ count }}</p> </CardWrapper> ```
Fix 2: Pass Reactive Data as Props Instead
<!-- Instead of slotting reactive content, pass it as props -->
<CardWrapper :title="title" :count="count">
<p>Static content here</p>
</CardWrapper>Fix 3: Force Re-render with Key
<CardWrapper :key="title + count">
<p>{{ title }}: {{ count }}</p>
</CardWrapper>Fix 4: Avoid Caching Slots
```vue <!-- WRONG: v-once prevents re-renders --> <CardWrapper> <p v-once>{{ title }}</p> </CardWrapper>
<!-- WRONG: Shallow ref does not deep-track changes --> const config = shallowRef({ title: 'Hello' }); ```