Skip to content

Duplicate title tag with React 19 #266

@w3bStuff

Description

@w3bStuff

My app has been using react 19 for a while and I recently upgraded react-helmet-async from version 2.0.5 to 3.0.0.
As a result my current logic that uses a <HelmetProvider> with a default <Helmet> component that sets a titleTemplate doesn't work any more.
Every single page of my SPA calls my custom component <CustomHelmet> that in turn sets the page title an meta data by calling <Helmet>:

export const CustomHelmet = (props: CustomHelmetProps) => {
  const applicationUrl = window?.location?.origin || "";
  const absoluteUrl = props.url?.startsWith("/")
    ? `${applicationUrl}${props.url}`
    : props.url;

  const location = useLocation();
  const currentUrl = `${applicationUrl}${location.pathname}`;

  return (
    <Helmet key={props.title}>
      {/* Standard metadata tags */}
      <title>{props.title}</title>
      <meta name="description" content={props.description} />
      <link rel="canonical" href={absoluteUrl ?? currentUrl} />

      {/* Facebook tags */}
      <meta property="og:type" content={props.type || "website"} />
      <meta property="og:title" content={props.title} />
      <meta property="og:description" content={props.description} />
      <meta property="og:url" content={absoluteUrl ?? currentUrl} />

      {/* Twitter tags */}
      <meta name="twitter:creator" content={props.name} />
      <meta name="twitter:card" content={props.type || "website"} />
      <meta name="twitter:title" content={props.title} />
      <meta name="twitter:description" content={props.description} />
    </Helmet>
  );
};

As a result of the upgrade, and as stated in the doc, "HelmetProvider becomes a transparent passthrough." and "Helmet renders actual DOM elements and lets React handle hoisting them to head".

My issue is that my SPA loads off a static HTML file that also contains a placeholder title tag. Once the app kicks in and a page is displayed, I end up with two <title> tags in my HTML <head>: the placeholder title tag and the custom one set in the page.

How to recover the previous behaviour without downgrading back to v2?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions