Index of every page on this site: llms.txt
React
Get Started

Migrating from React Helmet to Unhead

For the smallest initial change, swap your import to @unhead/react/helmet. Its compatibility component supports common React Helmet props such as defaultTitle, titleTemplate, and onChangeClientState. You can later replace <Helmet> with useHead() or <Head>.

Why migrate

React Helmet has long provided <head> management for React applications. Its latest tagged release, v6.1.0, was published in 2020.

Unhead adds:

React Helmet vs Unhead

React Helmet manages tags through <Helmet>. Unhead's <Head> component provides a similar JSX API.

React Helmet
import { Helmet } from 'react-helmet'

function App() {
  return (
    <Helmet>
      <title>My Site</title>
      <meta name="description" content="Description" />
    </Helmet>
  )
}
Unhead
import { Head } from '@unhead/react'

function App() {
  return (
    <Head>
      <title>My Site</title>
      <meta name="description" content="Description" />
    </Head>
  )
}

Migration

Quick Migration with @unhead/react/helmet

Unhead provides a <Helmet> compatibility component for common React Helmet usage, including defaultTitle, titleTemplate, and onChangeClientState.

1. Swap Your Dependencies

npm remove react-helmet
npm install @unhead/react

2. Update Your Imports

-import { Helmet } from 'react-helmet'
+import { Helmet } from '@unhead/react/helmet'

For the supported props, your existing <Helmet> usage can remain unchanged. On the client, <Helmet> automatically creates and manages a head instance, so no provider is needed. Check custom or less common React Helmet props before treating the component as a complete API replacement.

titleTemplate applies to a page title. When no title exists, defaultTitle is emitted unchanged.

For SSR, you still need to wrap your app with <UnheadProvider> so you can pass the head instance to renderSSRHead(). See Update Server Rendering below.
import { Helmet } from '@unhead/react/helmet'

function App() {
  return (
    <Helmet
      defaultTitle="My Site"
      titleTemplate="%s | My Site"
      onChangeClientState={(newState) => console.log(newState)}
    >
      <title>Page Title</title>
      <meta name="description" content="Description" />
    </Helmet>
  )
}
The encodeSpecialCharacters and defer props are accepted for compatibility but have no effect. Unhead handles both behaviors internally.

3. Full Migration to <Head> (Optional)

To adopt the Unhead API directly, replace <Helmet> with <Head>:

-import { Helmet } from 'react-helmet'
+import { Head } from '@unhead/react'

function Title() {
return (
  <div>
-    <Helmet titleTemplate="%s | My Site">
-      <title>Hello World</title>
-    </Helmet>
+    <Head titleTemplate="%s | My Site">
+      <title>Hello World</title>
+    </Head>
    <h1>Hello World</h1>
  </div>
  )
}

4. Update Server Rendering

If you're using SSR, update your server code:

src/entry-server.tsx
import { createHead, UnheadProvider } from '@unhead/react/server'
import { StrictMode } from 'react'
import { renderToString } from 'react-dom/server'
import App from './App'

export function render(_url: string) {
  const head = createHead()
  const html = renderToString(
    <StrictMode>
      <UnheadProvider value={head}>
        <App />
      </UnheadProvider>
    </StrictMode>,
  )
  return { html, head }
}

Next Steps

Migration Support

Did this page help you?