What Causes This Error?
This error occurs when you try to apply multiple hydration directives to the same component. Nuxt components can only have one hydration strategy at a time.
The Problem
<template>
<!-- ❌ Wrong - multiple hydration strategies -->
<LazyMyComponent
lazy-hydrate-on-visible
lazy-hydrate-on-idle
/>
<!-- ❌ Wrong - combining strategies -->
<LazyChart
:lazy-hydrate-on-visible="true"
:lazy-hydrate-on-interaction="['click']"
/>
</template>
The Fix
Choose One Strategy
<template>
<!-- ✅ Correct - single strategy -->
<LazyMyComponent lazy-hydrate-on-visible />
<!-- OR -->
<LazyMyComponent lazy-hydrate-on-idle />
<!-- OR -->
<LazyMyComponent :lazy-hydrate-on-interaction="['click', 'mouseover']" />
</template>
Understanding Hydration Strategies
Available Strategies
| Strategy | When It Hydrates |
|---|---|
lazy-hydrate-on-visible | Component enters viewport |
lazy-hydrate-on-idle | Browser is idle |
lazy-hydrate-on-interaction | User interacts (click, hover, etc.) |
lazy-hydrate-never | Never hydrates (static only) |
On Visible
<template>
<!-- Hydrates when scrolled into view -->
<LazyHeavyChart lazy-hydrate-on-visible />
<!-- With options -->
<LazyHeavyChart
lazy-hydrate-on-visible
:lazy-hydrate-options="{ rootMargin: '100px' }"
/>
</template>
On Idle
<template>
<!-- Hydrates when browser is idle -->
<LazyAnalytics lazy-hydrate-on-idle />
<!-- With timeout -->
<LazyAnalytics
lazy-hydrate-on-idle
:lazy-hydrate-options="{ timeout: 5000 }"
/>
</template>
On Interaction
<template>
<!-- Hydrates on any interaction -->
<LazyDropdown :lazy-hydrate-on-interaction="true" />
<!-- Hydrates on specific events -->
<LazyDropdown :lazy-hydrate-on-interaction="['click', 'focus']" />
<!-- Hydrates on mouseover -->
<LazyTooltip :lazy-hydrate-on-interaction="['mouseover']" />
</template>
Never Hydrate
<template>
<!-- Static content, never hydrates -->
<LazyStaticBanner lazy-hydrate-never />
</template>
Choosing the Right Strategy
Heavy Components Below Fold
<template>
<HeroSection /> <!-- Immediate hydration -->
<!-- Below fold - hydrate when visible -->
<LazyTestimonials lazy-hydrate-on-visible />
<LazyFooter lazy-hydrate-on-visible />
</template>
Analytics/Tracking
<template>
<!-- Non-critical, hydrate when idle -->
<LazyAnalyticsWidget lazy-hydrate-on-idle />
<LazyChatWidget lazy-hydrate-on-idle />
</template>
Interactive Elements
<template>
<!-- Needs interaction to work -->
<LazyModal :lazy-hydrate-on-interaction="['click']" />
<LazyAccordion :lazy-hydrate-on-interaction="['click']" />
</template>
Static Content
<template>
<!-- Never needs JS -->
<LazyLegalFooter lazy-hydrate-never />
<LazyStaticSidebar lazy-hydrate-never />
</template>
Alternative: Wrapper Component
If you need complex hydration logic, create a wrapper:
<!-- components/SmartHydrate.vue -->
<script setup>
const props = defineProps<{
priority: 'high' | 'medium' | 'low' | 'none'
}>()
</script>
<template>
<!-- High priority - immediate -->
<slot v-if="priority === 'high'" />
<!-- Medium priority - on visible -->
<ClientOnly v-else-if="priority === 'medium'">
<slot />
</ClientOnly>
<!-- Low priority - on idle -->
<LazyClientOnly v-else-if="priority === 'low'" lazy-hydrate-on-idle>
<slot />
</LazyClientOnly>
<!-- None - never hydrate -->
<div v-else>
<slot />
</div>
</template>
Usage:
<template>
<SmartHydrate priority="medium">
<MyComponent />
</SmartHydrate>
</template>
Combining with Lazy Loading
<template>
<!-- Lazy (code-split) + hydration strategy -->
<LazyExpensiveComponent lazy-hydrate-on-visible />
<!-- vs immediate load but delayed hydration -->
<ExpensiveComponent lazy-hydrate-on-idle />
</template>
Configuration
Enable delayed hydration in config:
// nuxt.config.ts
export default defineNuxtConfig({
experimental: {
// Required for hydration strategies
componentIslands: true
}
})
Debugging
Check hydration status:
<script setup>
// See when component hydrates
onMounted(() => {
console.log('Component hydrated at:', performance.now())
})
</script>
Quick Checklist
- Only one hydration strategy per component
- Choose strategy based on component priority
- Use
lazy-hydrate-on-visiblefor below-fold content - Use
lazy-hydrate-on-idlefor non-critical features - Use
lazy-hydrate-on-interactionfor interactive elements - Use
lazy-hydrate-neverfor static content - Enable
experimental.componentIslandsif needed