React 19 is not in the RC or Release Candidate Stage and while things might still change between now and release one particular new feature has generated a lot of buzz among developers and SEO experts - namely the head
changes. While it is a feature aimed at making things easier there has been a lot of talk about potential issues it may cause. Is that warranted?
The basics
If you're not that into SEO stuff the <head>
is a html tag at the top of the page where you put most of the SEO stuff like page title, meta tags, links, canonical and scripts like schema.org and google tag or analytics. If you put any of that anywhere outside the <head>
tag, like in the body of the page it wouldn't work. As such the usual application would be to have a helmet component which puts all the relevant SEO stuff in our pages.
Where's your head at?
From my experience with React projects we usually used a custom helmet component that was then included in the layout component and had a few simple props you needed to input for each page (title, meta description and canonical) and all the other SEO stuff would be handled by the custom helmet component.
Other typical use cases were using the Next head component provided natively by Next and inputting the SEO stuff directly there per page:
import Head from "next/head";
function IndexPage() {
return (
<div>
<Head>
<title>My page title</title>
<meta property="og:title" content="My page title" key="title" />
</Head>
<Head>
<meta property="og:title" content="My new title" key="title" />
</Head>
<p>Hello world!</p>
</div>
);
}
export default IndexPage;
Next also had native support for metadata:
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "...",
description: "...",
};
export default function Page() {}
For projects that didnt use Next there was the popular react helmet library (https://github.com/nfl/react-helmet) which basically did the same thing:
import React from "react";
import { Helmet } from "react-helmet";
class Application extends React.Component {
render() {
return (
<div className="application">
<Helmet>
<meta charSet="utf-8" />
<title>My Title</title>
<link rel="canonical" href="http://mysite.com/example" />
</Helmet>
...
</div>
);
}
}
React-helmet Custom approach
I never really used Next's native Head or Metada for a simple reason - it forced you to do it per page, which works for basic SEO like title and metadescription, but not much beyond that. For example for graphqleditor.com my customHelmet component which handles stuff like: truncating too long titles and metadescriptions, schema.org, link canonicals and alternates, og tags, google tag, posthog, fb pixel and whatever else has around 150 lines of code. Obviously sticking that code in every single page makes no sense, but splitting it up and using Next head or metadata for just titles and a customHelmet or react-helmet for the rest makes no sense either when instead I can keep all the SEO related stuff in once place. This way if anything goes wrong (which with SEO happens quite often) I'll need to look in just one component instead of in all the pages.
What are they actually changing?
As laid out in their blog post React 19 will natively support meta tags wherever you'll put them so you can just do <title>my title</title>
wherever in the page component or any child component and React will put that into the <head>
tag automatically. As they hint in their post this is meant to replace outside sources like react-helmet and next-head with native built in support.
export const BlogPost = () => {
return (
<article>
<h1>{title}</h1>
<title>{title}</title>
<meta name="description" content="a blogpost about bla blah blah..." />
<p>Lorem ipsum...</p>
</article>
);
};
Issues
So what's the big problem? While this is nice and makes sense for one-off usage I'm immediately sceptic about two things:
- inserting tags per page instead of doing it in one place via a helmet component
- possible tag duplication
As mentioned before keeping all the SEO related stuff in one place via a helmet component is easier and more clear to a dev or seo technician than spreading it out over each page component. Lets say I have an e-commerce shop with a custom helmet I can do something like this:
let title = shopData.pageTitle || fallbackTitle;
if (product && variant) {
title = `${product.name} ${product.variant} | ${shopName}`;
}
if (collection) {
title = `${collection.name} | ${shopName}`;
}
if (blogPost) {
title = `${post.title} by ${post.author}`;
}
if (title.length > 60) {
title = title.slice(0, -3) + "...";
}
This way I can handle titles for pages, blogs, product and collections - all in one place and have a fallback in case there is none provided as well as truncate them to fit googles 60 character limit. Using the native solution I would have to do that in each page component and as mentioned before I'm doing a bunch of other stuff in the helmet component I would also have to replicate.
Duped tags
Additionally the automatic rendering of every <title>
regardless of where it is can easily lead to tag duplications. Lets say some junior dev adds a new page with a <title>
tag because he doesn't know that we're already using react-helmet in the page layout component. This will now result in two titles in the head, with no clear indication of which one will actually be rendered. I for one am looking forward to searching for some title tag nested in some small component somewhere in the page (and I really when using Styled Components a <Title>
doesn't get treated the same way)
Not for me
While the new approach makes sense for basic usecases and will be appreciated by those who don't want to bother with SEO too much and just want their page titles and meta-descriptions I will definitely stick to using a custom helmet component to keep all my SEO stuff in one place instead of scattering it across all the pages. The possible pitfall with title duplication has some people a lot more worried (especially in regards to streaming html) but that will probably get fixed with how much attention it got from people online. Aside from that I doubt React Helmet will become less popular since (as of now at least) it still is a more efficient and easy to use approach which provides a bunch of additional seo related stuff out of the box aside from the basics. But if React continues adding more and more native feature support who knows?