Thread-safe Helmet for React 19+ and friends
npm install @dr.pogodin/react-helmet




Advanced management of document head's elements (, , ,, , , ), and of attributes of
and 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:
``sh`
npm install --save @dr.pogodin/react-helmet
At a high level, wrap the main application tree into [HelmetProvider]:
`tsx
import type { FunctionComponent } from 'react';
import { HelmetProvider } from '@dr.pogodin/react-helmet';
const YourApp: FunctionComponent = () => {
/ Whatever code you need. /
return (
{ / Your application tree. / }
);
}
`
Anywhere within the [HelmetProvider]'s children tree use [Helmet] component
to set / modify document head's elements, or supported attributes of
and elements. Instances of [Helmet] component within the application
tree add or override elements and attributes in the order these [Helmet]
instances are rendered.
`tsx
import type { FunctionComponent } from 'react';
import { Helmet } from '@dr.pogodin/react-helmet';const SomeComponent: FunctionComponent = () => {
/ Whatever code you need. /
return (
My Title
{ / Whatever other stuff you need. / } { /* For example, this other component will override the title
and description set earlier in the render tree. */ }
Overriden Title
)
};
`Alternatively, all elements and attributes specified by [Helmet] components may
be provided _via_ props instead of children.
`tsx
import type { FunctionComponent } from 'react';
import { Helmet } from '@dr.pogodin/react-helmet';const SomeComponent: FunctionComponent = () => {
/ Whatever code you need. /
return (
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 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. */ }
)
};
`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 data outside renderToNodeStream()):
`tsx
import type { FunctionComponent } from 'react';
import { type HelmetDataContext, HelmetProvider } from '@dr.pogodin/react-helmet';async function yourServerSideRenderingFunction() {
// ...
const context: HelmetDataContext = {};
const { prelude } = await prerenderToNodeStream(
{ / Your application tree. / }
);
// ...
// For example, this is how you get the string representation of tags
// to be injected into your document head.
const metaElements = context.helmet.meta?.toString();
}
`Prioritizing Tags for SEO
[Prioritizing Tags for SEO]: #prioritizing-tags-for-seoIt is understood that in some cases for SEO, certain tags should appear earlier
in the HEAD. Using the
prioritizeSeoTags flag on any component
allows the server render of @dr.pogodin/react-helmet to expose a method for
prioritizing relevant SEO tags.In the component:
`tsx
A fancy webpage
`In your server template:
`tsx
${helmet.title.toString()}
${helmet.priority.toString()}
${helmet.meta.toString()}
${helmet.link.toString()}
${helmet.script.toString()}
...
`Will result in:
`html
A fancy webpage
...
`A list of prioritized tags and attributes (
SEO_PRIORITY_TAGS) can be found in
constants.ts.Reference
[Reference]: #reference$3
[Helmet]: #helmetThe [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:
`tsx
// JSX code:
defaultTitle="My Site"
titleTemplate"My Site - %s"
/> // DOM output:
My Site
`-
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 documented_
- addedTags — _To be documented_
- removedTags — _To be documented_-
prioritizeSeoTags — _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._
`tsx
// JSX code:
Nested Title
// DOM output:
Nested Title | MyAwesomeWebsite.com
`Children
`tsx
{/ html attributes /}
{/ body attributes /}
{/ title attributes and value /}
} title {/ base element /}
{/ multiple meta elements /}
{/ multiple link elements /}
{locales.map((locale) => {
})}
{/ multiple script elements /}
{/ inline script elements /}
{/ noscript elements /}
{/ inline style elements /}
$3
[HelmetDataContext]: #helmetdatacontextThe [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:
`tsx
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;
};
`$3
[HelmetProvider]: #helmetproviderThe [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.$3
[MetaTags]: #metatags
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:
- and tags.
- Meta tags for [Open Graph].
- Meta tags for [Twitter (X) Cards].`tsx
// Simple Example.import type { FunctionComponent } from 'react';
import { MetaTags } from '@dr.pogodin/react-helmet';
const Example: FunctionComponent = () => (
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 = () => (
Example page title
);
`
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 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:
`tsx
import { type FunctionComponent, use } from 'react';
import { MetaTags } from '@dr.pogodin/react-helmet'; const Child: FunctionComponent = () => {
// These are values injected by parent component, if any.
const { title, description, ...rest } = use(MetaTags.Context);
// Say, you may modify the "parent" title like this:
return ${title} / Child Component} />;
};
const Parent: FunctionComponent = () => (
);
`-
extraMetaTags — Array<\{ content: string; name: string \}>
— Allows to add additional, arbitrary 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.[Open Graph]: https://ogp.me
[React Context]: https://react.dev/learn/passing-data-deeply-with-context
[Twitter (X) Cards]: https://developer.x.com/en/docs/x-for-websites/cards/overview/abouts-cards