Svelte
You're viewing Unhead v3 beta documentation.
Core Concepts

Reactivity in Svelte

Quick Answer: In Svelte 5, use $state() with useHead() inside $effect(). In Svelte 4, use writable stores. Head tags update automatically when state changes.

Introduction

Unhead integrates with Svelte's reactivity system through the Svelte context API. This guide explains how to effectively manage reactive head tags in your Svelte applications.

How Does Unhead Work in Svelte?

Unhead registers itself in the Svelte context, making head management available throughout your component tree. Each component can create head entries that automatically clean up when the component is destroyed.

How Do I Create Reactive Head Tags?

Svelte doesn't support reactivity outside of components. To create reactive head tags, you need to:

  1. Initialize a head entry using useHead()
  2. Use the returned patch() function within a Svelte $effect to update when state changes

Basic Pattern

<script lang="ts">
import { useHead } from '@unhead/svelte'

// Reactive state
let title = $state('My Page Title')

// Create a head entry instance
const entry = useHead()

// Set up the reactive effect
$effect(() => {
  entry.patch({
    title,
    meta: [
      { name: 'description', content: `Description for ${title}` }
    ]
  })
})

function updateTitle() {
  title = 'Updated Title'
}
</script>

<button on:click={updateTitle}>Update Title</button>

What Are the Best Practices?

Initialize Once, Patch Often

Create the head entry once, outside of the effect, and use patch() within the effect:

// ✅ Good: Create entry once
const entry = useHead()

$effect(() => {
  entry.patch({ title })
})

// ❌ Avoid: Creating new entry on each update
$effect(() => {
  useHead({ title })
})

This pattern prevents unnecessary memory allocations and ensures proper cleanup.

Does Unhead Handle Component Cleanup?

Yes. Unhead automatically handles cleanup when a component is unmounted. The onDestroy lifecycle hook is used internally to dispose of head entries when the component is removed from the DOM.

Advanced Usage

What Happens With Multiple Components?

When multiple components modify the same head properties, Unhead handles priorities based on mount order (later components have higher priority):

<!-- ComponentA.svelte -->
<script>
import { useHead } from '@unhead/svelte'

let count = $state(0)
const entry = useHead()

$effect(() => {
  entry.patch({
    title: `Count A: ${count}`
  })
})
</script>

<!-- ComponentB.svelte -->
<script>
import { useHead } from '@unhead/svelte'

let count = $state(0)
const entry = useHead()

$effect(() => {
  entry.patch({
    title: `Count B: ${count}`
  })
})
</script>

In this example, ComponentB's title will be shown if both components are mounted, as it was mounted last.

Can I Use Other Composables Reactively?

The same reactivity pattern applies to other Unhead composables:

<script>
import { useSeoMeta } from '@unhead/svelte'

let title = $state('My Page')
let description = $state('Page description')

const entry = useSeoMeta()

$effect(() => {
  entry.patch({
    title,
    description
  })
})
</script>

How Does Unhead Integrate With Svelte?

Unhead in Svelte works by:

  1. Creating a head instance with Svelte's tick() for DOM updates
  2. Making the head instance available via Svelte's context API
  3. Managing side effects with onDestroy for automatic cleanup
  4. Using $effect to track state changes and update head entries

This integration ensures that your head tags stay in sync with your component state while maintaining performance.

Did this page help you?