Advanced management of document head's elements (<base>
, <link>
, <meta>
,
<noscript>
, <script>
, <style>
, <title>
), and of attributes of <body>
and <html>
elements in React 19+ applications. This library is a proud
successor of now unmaintained and stale
react-helmet-async and
react-helmet libraries.
To install the library:
npm install --save @dr.pogodin/react-helmet
At a high level, wrap the main application tree into HelmetProvider:
import type { FunctionComponent } from 'react';
import { HelmetProvider } from '@dr.pogodin/react-helmet';
const YourApp: FunctionComponent = () => {
/* Whatever code you need. */
return (
<HelmetProvider>
{ /* Your application tree. */ }
</HelmetProvider>
);
}
Anywhere within the HelmetProvider's children tree use Helmet component
to set / modify document head's elements, or supported attributes of <body>
and <html>
elements. Instances of Helmet component within the application
tree add or override elements and attributes in the order these Helmet
instances are rendered.
import type { FunctionComponent } from 'react';
import { Helmet } from '@dr.pogodin/react-helmet';
const SomeComponent: FunctionComponent = () => {
/* Whatever code you need. */
return (
<div>
<Helmet>
<title>My Title</title>
<link rel="canonical" href="http://mysite.com/example" />
<meta charSet="utf-8" />
<meta name="description" content="Some Component" />
</Helmet>
{ /* Whatever other stuff you need. */ }
{ /* For example, this other <Helmet> component will override the title
and description set earlier in the render tree. */ }
<Helmet>
<title>Overriden Title</title>
<meta name="description" content="Overriden Component Description" />
</Helmet>
</div>
)
};
Alternatively, all elements and attributes specified by Helmet components may be provided via props instead of children.
import type { FunctionComponent } from 'react';
import { Helmet } from '@dr.pogodin/react-helmet';
const SomeComponent: FunctionComponent = () => {
/* Whatever code you need. */
return (
<div>
<Helmet
title="My Title"
link={[{
href: 'http://mysite.com/example',
rel: 'canonical',
}]}
meta={[{
charSet: 'utf-8',
}, {
content: 'Some Component',
name: 'description',
}]}
/>
{ /* Whatever other stuff you need. */ }
{ /* For example, this other <Helmet> component will override the title
and description set earlier in the render tree. It is also fine to
use a mix of props and children. */ }
<Helmet title="Overriden Title">
<meta name="description" content="Overriden Component Description" />
</Helmet>
</div>
)
};
For the server-side rendering purposes you pass in a context
object to
the HelmetProvider, and after the render you use that object to retrieve
the string, or component representation of the elements and attributes to be
injected into the document head (if you use streaming for server side rendering
you should output your <head>
data outside renderToNodeStream()
):
import type { FunctionComponent } from 'react';
import { type HelmetDataContext, HelmetProvider } from '@dr.pogodin/react-helmet';
async function yourServerSideRenderingFunction() {
// ...
const context: HelmetDataContext = {};
const { prelude } = await prerenderToNodeStream(
<HelmetProvider context={context}>
{ /* Your application tree. */ }
</HelmetProvider>
);
// ...
// For example, this is how you get the string representation of <meta> tags
// to be injected into your document head.
const metaElements = context.helmet.meta?.toString();
}
It is understood that in some cases for SEO, certain tags should appear earlier
in the HEAD. Using the prioritizeSeoTags
flag on any <Helmet>
component
allows the server render of @dr.pogodin/react-helmet to expose a method for
prioritizing relevant SEO tags.
In the component:
<Helmet prioritizeSeoTags>
<title>A fancy webpage</title>
<link rel="notImportant" href="https://www.chipotle.com" />
<meta name="whatever" value="notImportant" />
<link rel="canonical" href="https://www.tacobell.com" />
<meta property="og:title" content="A very important title"/>
</Helmet>
In your server template:
<html>
<head>
${helmet.title.toString()}
${helmet.priority.toString()}
${helmet.meta.toString()}
${helmet.link.toString()}
${helmet.script.toString()}
</head>
...
</html>
Will result in:
<html>
<head>
<title>A fancy webpage</title>
<meta property="og:title" content="A very important title"/>
<link rel="canonical" href="https://www.tacobell.com" />
<meta name="whatever" value="notImportant" />
<link rel="notImportant" href="https://www.chipotle.com" />
</head>
...
</html>
A list of prioritized tags and attributes (SEO_PRIORITY_TAGS
) can be found in
constants.ts.
The Helmet component specifies (document head) elements and attributes to be created / set / overriden by the library. Different Helmet instances within the application tree (within the single HelmetProvider) have effect in the order they are encountered (mounted to DOM) during the render.
The Helmet component exposes two equivalent APIs — the elements / attributes may be provided either as component's children (i.e. written as regular JSX component children), or as Helmet component props. Both these APIs can also be used at the same time, with values provided as props handled as additional JSX children, appearing prior the explicitly provided JSX children.
Props
base
— To be documented
bodyAttributes
— To be documented
defaultTitle
— string | undefined — Optional.
The fallback to use when titleTemplate
(below) prop is provided,
but no title was specified:
// JSX code:
<Helmet
defaultTitle="My Site"
titleTemplate"My Site - %s"
/>
// DOM output:
<head>
<title>My Site</title>
</head>
defer
— boolean | undefined — Optional. Defaults true.
set to false to not use requestAnimationFrame
and instead update the DOM
as soon as possible. Useful if you want to update the title when the tab is
out of focus.
encodeSpecialCharacters
— boolean | undefined —
Optional. Defaults true. Set false to disable string encoding by
.toString()
methods of HelmetDataContext.
htmlAttributes
— To be documented
link
— To be documented
meta
— To be documented
noscript
— To be documented
onChangeClientState
— function | undefined — Optional.
A callback to trigger on client-side each time the head elements / attributes
are updated. It will be called with three arguments:
newState
— To be documentedaddedTags
— To be documentedremovedTags
— To be documentedprioritizeSeoTags
— To be documented
script
— To be documented
style
— To be documented
title
— To be documented
titleAttributes
— To be documented
titleTemplate
— string | undefined — Optional.
Allows to inherit title from a template, e.g.
// JSX code:
<Helmet titleTemplate="%s | MyAwesomeWebsite.com">
<title>Nested Title</title>
</Helmet>
// DOM output:
<head>
<title>Nested Title | MyAwesomeWebsite.com</title>
</head>
Children
<Helmet>
{/* html attributes */}
<html lang="en" amp />
{/* body attributes */}
<body className="root" />
{/* title attributes and value */}
<title itemProp="name" lang="en">My Plain Title or {`dynamic`} title</title>
{/* base element */}
<base target="_blank" href="http://mysite.com/" />
{/* multiple meta elements */}
<meta name="description" content="Helmet application" />
<meta property="og:type" content="article" />
{/* multiple link elements */}
<link rel="canonical" href="http://mysite.com/example" />
<link rel="apple-touch-icon" href="http://mysite.com/img/apple-touch-icon-57x57.png" />
<link rel="apple-touch-icon" sizes="72x72" href="http://mysite.com/img/apple-touch-icon-72x72.png" />
{locales.map((locale) => {
<link rel="alternate" href="http://example.com/{locale}" hrefLang={locale} key={locale}/>
})}
{/* multiple script elements */}
<script src="http://include.com/pathtojs.js" type="text/javascript" />
{/* inline script elements */}
<script type="application/ld+json">{`
{
"@context": "http://schema.org"
}
`}</script>
{/* noscript elements */}
<noscript>{`
<link rel="stylesheet" type="text/css" href="foo.css" />
`}</noscript>
{/* inline style elements */}
<style type="text/css">{`
body {
background-color: blue;
}
p {
font-size: 12px;
}
`}</style>
</Helmet>
The HelmetDataContext (it may be initialized as just an empty object) can be
provided to HelmetProvider for server-side rendering (SSR) purposes. After
the component tree has been rendered, the helmet
field will be attached to
this context:
type HelmetDataContext = {
helmet?: {
base: HelmetDatum;
bodyAttributes: HelmetDatum;
htmlAttributes: HelmetDatum;
link: HelmetDatum;
meta: HelmetDatum;
noscript: HelmetDatum;
script: HelmetDatum;
style: HelmetDatum;
title: HelmetDatum;
titleAttributes?: HelmetDatum;
priority: HelmetDatum;
};
};
// where each HelmetDatum has two methods allowing to get string and component
// representations of the corresponding elements or attrbiutes:
type HelmetDatum = {
toString(): string;
toComponent(): ReactNode;
};
The HelmetProvider component provides React Context to Helmet components, i.e. any Helmet components in the application tree must be descendants of a single HelmetProvider instance.
Props
children
— ReactNode — The component tree to render in
the place of HelmetProvider.context
— HelmetDataContext | undefined — Optional.
A user-provided context object for server-side rendering (SSR) purposes.The MetaTags component is a helper for easier rendering of page title, description, and misc meta tags for search engines and social graphs (i.e. for previews of linked pages in social media, messengers, etc.). Based on provided properties it uses Helmet to render:
<title>
and <meta name="description">
tags.// Simple Example.
import type { FunctionComponent } from 'react';
import { MetaTags } from '@dr.pogodin/react-helmet';
const Example: FunctionComponent = () => (
<MetaTags
description="Example page description"
title="Example page title"
/>
);
// It is completely equivalent to:
import type { FunctionComponent } from 'react';
import { Helmet } from '@dr.pogodin/react-helmet';
const EquivalentComponent: FunctionComponent = () => (
<Helmet>
<title>Example page title</title>
<meta content="Example page description" name="description" />
<meta content="summary_large_image" name="twitter:card" />
<meta content="Example page title" name="twitter:title" />
<meta content="Example page description" name="twitter:description" />
<meta content="Example page title" name="og:title" />
<meta content="Example page description" name="og:description" />
</Helmet>
);
As this example demonstrates, MetaTags must not be wrapped into Helmet, as it will render its instance itself, but the same as Helmet components, all MetaTags instances should be descendants of HelmetProvider within the application component tree.
Multiple MetaTags within the application tree override the tags they manage according to the usual Helmet logic.
Required Properties:
description
— string — Page description to use in
the description meta tag, and as the default description in Open Graph
and Twitter (X) Cards.
title
— string — The page name to use in the <title>
tag,
and as the default title in Open Graph and Twitter (X) Cards.
Optional Properties:
children
— ReactNode — Component children, if any,
are rendered at the component's place.
All meta data injected by MetaTags instance are passed down the children tree using an auxiliary context, thus facilitating tags modification by children. For example:
import { type FunctionComponent, use } from 'react';
import { MetaTags } from '@dr.pogodin/react-helmet';
const Child: FunctionComponent = () => {
// These are values injected by parent <MetaTags> component, if any.
const { title, description, ...rest } = use(MetaTags.Context);
// Say, you may modify the "parent" title like this:
return <MetaTags title={`${title} / Child Component`} />;
};
const Parent: FunctionComponent = () => (
<MetaTags title="Parent Component">
<Child />
</MetaTags>
);
extraMetaTags
— Array<{ content: string; name: string }>
— Allows to add additional, arbitrary <meta>
tags to the page, with
given content
and name
strings.
image
— string — The absolute URL of thumbnail image to use
in Open Graph and Twitter (X) Cards meta tags (twitter:image
,
and og:image
). By default these tags are not injected.
BEWARE: The value must be a complete, absolute URL, including the correct website domain and HTTP schema.
siteName
— string — The site name to use in twitter:site
,
and og:sitename
meta tags. By default these tags are not injected.
socialDescription
— string — The site description to use in
twitter:description
and og:description
meta tags. By default the value of
description
prop is used.
socialTitle
— string — The page title to use in twitter:title
,
og:title
, and og:image:alt
meta tags. By default the value of title
prop
is used. Also the og:image:alt
tag is only injected if image
prop
is present.
url
— string — The page URL to use in og:url
meta tag.
By default the tag is not injected.