Hooks
dom:beforeRender Hook
On this page
The dom:beforeRender
hook is called before tags are rendered to the DOM in client-side environments. This hook allows you to control whether rendering should proceed and provides access to rendering context.
Hook Signature
export interface Hook {
'dom:beforeRender': (ctx: DomBeforeRenderCtx) => HookResult
}
Parameters
Name | Type | Description |
---|---|---|
ctx | DomBeforeRenderCtx | Context object with rendering information |
The DomBeforeRenderCtx
interface extends ShouldRenderContext
:
interface DomBeforeRenderCtx extends ShouldRenderContext {
tags: DomRenderTagContext[] // Note: this is deprecated and will always be empty
}
interface ShouldRenderContext {
shouldRender: boolean
}
Returns
HookResult
which is either void
or Promise<void>
Usage Example
import { createHead } from '@unhead/react'
const head = createHead({
hooks: {
'dom:beforeRender': (ctx) => {
// Log rendering intent
console.log('About to render tags to DOM')
// You can prevent rendering by setting shouldRender to false
if (window.document.querySelector('meta[name="unhead-rendered"]')) {
console.log('Preventing re-render as tags are already rendered')
ctx.shouldRender = false
}
}
}
})
Use Cases
Conditional Rendering
Control whether rendering should proceed based on page conditions:
import { defineHeadPlugin } from '@unhead/react'
export const conditionalRenderPlugin = defineHeadPlugin({
hooks: {
'dom:beforeRender': (ctx) => {
// Only render head tags if we're not in a specific context
if (window.location.pathname.startsWith('/admin')) {
// For admin pages, we want to prevent automatic rendering
// because we'll handle it differently
ctx.shouldRender = false
}
// Prevent rendering during specific user interactions
if (document.body.classList.contains('modal-open')) {
// Don't update head while modal is open to prevent flickering
ctx.shouldRender = false
}
}
}
})
Render Preparation
Prepare the DOM environment before rendering:
import { defineHeadPlugin } from '@unhead/react'
export const renderPreparationPlugin = defineHeadPlugin({
hooks: {
'dom:beforeRender': () => {
// Add rendering flag to prevent duplicate processing
if (!document.querySelector('meta[name="unhead-render-id"]')) {
const meta = document.createElement('meta')
meta.setAttribute('name', 'unhead-render-id')
meta.setAttribute('content', Date.now().toString())
document.head.appendChild(meta)
}
// Clean up specific tags that we always want to manage ourselves
const existingCanonical = document.querySelector('link[rel="canonical"]')
if (existingCanonical) {
existingCanonical.remove()
}
}
}
})
Delayed Rendering
Set up delayed rendering for better performance:
import { defineHeadPlugin } from '@unhead/react'
export const delayedRenderPlugin = defineHeadPlugin({
hooks: {
'dom:beforeRender': (ctx) => {
// Check if this is the initial page load
const isInitialLoad = !document.querySelector('[data-unhead-rendered]')
if (isInitialLoad) {
// For initial load, we can delay non-critical head updates
// until the page has finished loading
if (document.readyState !== 'complete') {
// Delay rendering until page is complete
ctx.shouldRender = false
// Set up listener to trigger rendering when ready
window.addEventListener('load', () => {
// Force head to re-evaluate rendering
setTimeout(() => {
head.hooks.callHook('entries:updated', head)
}, 0)
}, { once: true })
}
}
}
}
})
Did this page help you?