Index of every page on this site: llms.txt
TypeScript
Core Concepts

Handling DOM Events

Pass functions to supported on* properties. Scripts support onload and onerror; stylesheet, preload, and module-preload links support load and error events; bodyAttrs supports window-level body events.

Rendering and hydration

On the client, Unhead installs listeners with addEventListener() and removes or replaces them when the owning entry changes. Functions are not serialized into HTML.

During SSR, a function handler is rendered as a small marker handler such as:

<script onload="this.dataset.onloadfired = true"></script>

If the event fires before hydration, the marker lets the client renderer replay the handler with a synthetic event after adopting the element. You should therefore register the same handler during SSR and hydration. Wrapping useHead() in if (import.meta.client) removes this replay path and can also produce different server and client head entries.

Content Security Policy

On the client, Unhead never writes inline event handlers: listeners go through addEventListener(), so strict CSP policies that block inline handlers stay clean.

During SSR, a function handler is rendered as the marker attribute shown above, for example onload="this.dataset.onloadfired = true". A strict policy such as script-src-attr 'none' blocks execution of this inline handler and reports a CSP violation in the browser console. The marker only powers handler replay for events that fire before hydration; the resource itself still loads, and handlers registered on the client keep working after hydration.

Resource events

import { useHead } from 'unhead'

useHead(unheadInstance, {
  link: [
    {
      rel: 'stylesheet',
      href: '/assets/critical.css',
      onload: event => console.log('Stylesheet loaded', event),
      onerror: event => console.error('Stylesheet failed', event)
    }
  ],
  script: [
    {
      src: '/assets/app.js',
      defer: true,
      onload: event => console.log('Script loaded', event),
      onerror: event => console.error('Script failed', event)
    }
  ]
})

Browsers fire load after a stylesheet and its imports have loaded and parsed, and error if stylesheet processing fails. Script elements likewise receive load or error after the external resource is accepted or rejected. See the MDN references for <link> load events and <script> loading.

Use useScript() when you need triggers, a load promise, API resolution, warmup hints, or reusable onLoaded() and onError() callbacks.

Body events

Handlers under bodyAttrs are attached to window, with this bound to document.body. Each handler receives its native Event object.

import { useHead } from 'unhead'

useHead(unheadInstance, {
  bodyAttrs: {
    onresize(event) {
      console.log('Window resized', event)
    },
    onoffline() {
      showNotification('You are offline.')
    },
    ononline() {
      showNotification('You are back online.')
    }
  }
})

Supported body event names include onafterprint, onbeforeprint, onbeforeunload, onerror, onhashchange, onload, onmessage, onoffline, ononline, onpagehide, onpageshow, onpopstate, onresize, onstorage, and onunload.

Cleanup

Unhead removes a listener when its entry is patched without that handler or when the entry is disposed. The return value of an event handler is ignored; returning a cleanup function from onload does not register cleanup work.

If a handler creates its own observer, timer, or subscription, clean that resource up through your framework's component lifecycle.

See Also

Did this page help you?