Solid.js
You're viewing Unhead v3 beta documentation.
Core Concepts

Reactivity in Solid.js

Quick Answer: In Solid, use signals with useHead() inside createEffect(). Pass getter functions for reactive values. Head tags update automatically with signal changes.

Introduction

Unhead integrates seamlessly with Solid.js's fine-grained reactivity system. This guide explains how to effectively manage reactive head tags in your Solid.js applications.

How Does Unhead Work in Solid.js?

Unhead for Solid.js leverages Solid's reactive primitives including signals, effects, and contexts to provide a reactive head management solution. When your application state changes, Solid.js's reactivity system automatically ensures your head tags reflect the current state.

How Do I Set Up UnheadContext?

Unhead uses Solid.js's Context API to provide head management throughout your component tree:

import { createHead, UnheadContext } from '@unhead/solid-js/client'
import { render } from 'solid-js/web'
import App from './App'

const head = createHead()

render(() => (
  <UnheadContext.Provider value={head}>
    <App />
  </UnheadContext.Provider>
), document.getElementById('root'))

This pattern keeps head state contained and manageable, making components more testable and preventing hydration issues.

How Do I Use Signals with useHead()?

Solid.js's signals work naturally with Unhead. When you pass signals to useHead(), the head tags update whenever the signal values change:

import { useHead } from '@unhead/solid-js'
import { createSignal } from 'solid-js'

function PageHead() {
  const [title, setTitle] = createSignal('Welcome to My App')

  // Head tags will update when title signal changes
  useHead(() => ({
    title: title()
  }))

  return (
    <button onClick={() => setTitle('Updated Title')}>
      Update Title
    </button>
  )
}

Direct Signal Integration

You can also pass signals directly to useHead():

import { useHead } from '@unhead/solid-js'
import { createSignal } from 'solid-js'

function PageHead() {
  const [title, setTitle] = createSignal('Welcome to My App')
  const [description, setDescription] = createSignal('My site description')

  useHead({
    get title() { return title() },
    meta: [
      {
        name: 'description',
        get content() { return description() }
      }
    ]
  })

  return (
    <>
      <button onClick={() => setTitle('Updated Title')}>Update Title</button>
      <button onClick={() => setDescription('New description')}>Update Description</button>
    </>
  )
}

How Do I Update Head Tags with Async Data?

It's common to update head tags based on asynchronous data:

import { useHead } from '@unhead/solid-js'
import { createResource, createSignal } from 'solid-js'

async function fetchPageData(id) {
  const response = await fetch(`/api/page/${id}`)
  return response.json()
}

function PageHead({ id }) {
  const [pageData] = createResource(() => id, fetchPageData)

  useHead(() => ({
    title: pageData()?.title || 'Loading...',
    meta: [
      {
        name: 'description',
        content: pageData()?.description || 'Loading page content...'
      }
    ]
  }))

  return null
}

How Do I Manage Multiple Meta Tags Together?

For pages with multiple meta tags, you can manage them together with Solid.js's reactive primitives:

import { useHead } from '@unhead/solid-js'
import { createResource } from 'solid-js'

async function fetchProduct(id) {
  const response = await fetch(`/api/products/${id}`)
  return response.json()
}

function ProductHead({ id }) {
  const [product] = createResource(() => id, fetchProduct)

  useHead(() => ({
    title: product()?.title || 'Loading Product...',
    meta: [
      { name: 'description', content: product()?.description || '' },
      { property: 'og:image', content: product()?.image || '/placeholder.jpg' },
      { property: 'product:price', content: product()?.price || '' }
    ]
  }))

  return null
}

How Do I Create Reusable Head Components?

Solid.js's composable nature makes it easy to create reusable head components:

import { useHead } from '@unhead/solid-js'
import { mergeProps } from 'solid-js'

function SEOHead(props) {
  const merged = mergeProps({
    title: 'Default Title',
    description: 'Default description',
    ogImage: '/default-og.jpg'
  }, props)

  useHead(() => ({
    title: merged.title,
    meta: [
      { name: 'description', content: merged.description },
      { property: 'og:title', content: merged.title },
      { property: 'og:description', content: merged.description },
      { property: 'og:image', content: merged.ogImage }
    ]
  }))

  return null
}

// Usage
function HomePage() {
  return (
    <div>
      <SEOHead
        title="Home Page"
        description="Welcome to our website"
      />
      {/* Page content */}
    </div>
  )
}

How Do I Conditionally Render Head Tags?

You can leverage Solid.js's control flow primitives to conditionally render head tags:

import { useHead } from '@unhead/solid-js'
import { createEffect, createSignal, Show } from 'solid-js'

function DynamicHead() {
  const [isLoggedIn, setIsLoggedIn] = createSignal(false)
  const [user, setUser] = createSignal(null)

  // Simulate login
  const login = () => {
    setUser({ name: 'John Doe', id: '123' })
    setIsLoggedIn(true)
  }

  createEffect(() => {
    if (isLoggedIn()) {
      useHead({
        title: `Dashboard - ${user().name}`,
        meta: [
          { name: 'description', content: 'Your personal dashboard' }
        ]
      })
    }
    else {
      useHead({
        title: 'Login',
        meta: [
          { name: 'description', content: 'Login to access your dashboard' },
          { name: 'robots', content: 'noindex' }
        ]
      })
    }
  })

  return (
    <div>
      <Show when={isLoggedIn()} fallback={<button onClick={login}>Login</button>}>
        <h1>
          Welcome,
          {user().name}
          !
        </h1>
      </Show>
    </div>
  )
}

How Does Unhead Work Under the Hood?

Under the hood, Unhead in Solid.js:

  1. Uses Solid.js's Context API for head instance management
  2. Integrates with Solid.js's reactivity system using createEffect
  3. Creates head entries that update reactively when input props change
  4. Automatically cleans up with onCleanup when components are disposed

The implementation wraps head entries with Solid.js's reactive primitives that:

  • Patch the entry when input data changes
  • Dispose of the entry when the component is disposed

What Are the Best Practices?

  1. Leverage Solid.js's Reactivity: Use signals, memos, and resources for reactive head data.
  2. Handle Loading States: Always provide fallback values for async data to prevent undefined errors.
  3. Use Component Composition: Compose multiple head components for complex pages:
function ProductPage(props) {
  return (
    <>
      <GlobalHead />
      <ProductHead id={props.id} />
      <ProductSchema id={props.id} />
      {/* UI components */}
    </>
  )
}
  1. Keep Head Components Focused: Create dedicated components for head management that are separate from UI components.
  2. Cleanup Happens Automatically: Unhead handles cleanup when components are disposed through Solid.js's cleanup system.
Did this page help you?