Tutorial

How To Change the Title and Metadata with React Helmet

React

Introduction

React Helmet is a component to dynamically manage the document’s head section. Some common use cases include setting the title, description, and meta tags for the document.

When combined with server-side rendering, it allows you to set meta tags that will be read by search engines and social media crawlers. This makes server-side rendering and React Helmet a powerful combination for creating apps that can benefit from SEO (search engine optimization) and social media data like oEmbed, Facebook Open Graph, or Twitter Cards.

In this article, you will explore the functionality of React Helmet in a React application.

Prerequisites

To follow along with this article, you will need:

  • Familiarity with installing packages with a package manager like npm or yarn.
  • Familiarity with importing and using components in your React project.

Note: This tutorial will not cover the steps for creating a React project or setting up server-side rendering. Please refer to How to Enable Server-Side Rendering for a React App.

This tutorial was verified with Node v15.3.0, npm v6.14.9, react v17.0.1, and react-helmet v6.1.0.

Step 1 — Adding React Helmet to Your Project

First, install the component into your project:

  • npm install react-helmet@6.1.0

Now you can use React Helmet in your app by adding the elements that should go in the head of the document as children to the Helmet component:

src/App.js
import { Helmet } from 'react-helmet';

function App() {
  return (
    <div className="App">
      <Helmet>
        <title>App Title</title>
        <meta name="description" content="App Description" />
        <meta name="theme-color" content="#008f68" />
      </Helmet>
    </div>
  );
}

export default App;

Then, open your browser’s developer tools and inspect the head element:

Inspect Element
<head> <!-- ... ---> <title>App Title</title> <!-- ... --> <meta name="description" content="App Description" data-react-helmet="true"> <meta name="theme-color" content="#008f68" data-react-helmet="true"> <!-- ... ---> </head>

Observe the title and meta elements added by React Helmet.

Step 2 — Overwriting Values

Components further down the tree can override values provided to the Helmet component on a higher level.

For example, consider a ChildComponent that contains a Helmet component that modifies title:

src/ChildComponent.js
import React from 'react';
import { Helmet } from 'react-helmet';

export default function ChildComponent() {
  return (
    <div>
      <Helmet>
        <title>Modified Title</title>
      </Helmet>
      <h1>Child Component</h1>
    </div>
  )
}

Next, revisit App component and include the new ChildComponent:

src/App.js
import { Helmet } from 'react-helmet';

import ChildComponent from './ChildComponent';

function App() {
  return (
    <div className="App">
      <Helmet>
        <title>App Title</title>
        <meta name="description" content="App Description" />
        <meta name="theme-color" content="#008f68" />
      </Helmet>
      <ChildComponent />
    </div>
  );
}

Then, open your browser’s developer tools and inspect the head element:

Inspect Element
<head> <!-- ... ---> <title>Modified Title</title> <!-- ... --> <meta name="description" content="App Description" data-react-helmet="true"> <meta name="theme-color" content="#008f68" data-react-helmet="true"> <!-- ... ---> </head>

The title will be changed from App Title to Modified Title. The meta tags for description and theme-color values will remain the same because they have not been overwritten.

Step 3 — Handling Attributes for html and body

You can even include the html and body elements if you need to specify attributes for them.

For example, consider a body element that has a dark theme applied to it:

src/App.js
import { Helmet } from 'react-helmet';

function App() {
  return (
    <div className="App">
      <Helmet>
        <title>App Title</title>
        <meta name="description" content="App Description" />
        <meta name="theme-color" content="#008f68" />
        <body class="dark" />
      </Helmet>
    </div>
  );
}

Then, open your browser’s developer tools and inspect the body element:

[seconday_label Inspect Element]
<body class="dark" data-react-helmet="class">
  <!-- ... -->
</body>

The class will be set to dark.

Step 4 — Rendering on the Server

The full benefit of React Helmet becomes apparent when the app is rendered on the server so that the app gets served with the correct elements in the head of the document.

Assuming that you have a React server-side rendered app setup in place, you can call React Helmet’s renderStatic method right after calling ReactDOMServer’s renderToString or renderToStaticMarkup to get an instance with properties for the Helmet data:

server/index.js
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import express from 'express';
import { Helmet } from 'react-helmet';

import App from '../src/App';

const PORT = process.env.PORT || 3006;
const app = express();

app.get('/*', (req, res) => {
  const appString = ReactDOMServer.renderToString(<App />);
  const helmet = Helmet.renderStatic();

  const html = `<!DOCTYPE html>
    <html lang="en">
      <head>
        ${helmet.title.toString()}
        ${helmet.meta.toString()}
      </head>
      <body>
        <div id="root">
          ${ appString }
        </div>
      </body>
    </html>
  `

  res.send(html);
});

app.listen(PORT);

Calling Helmet’s renderStatic returns an instance with properties like title and meta. You will also have access to other properties like link, script, noscript, style, htmlAttributes, and bodyAttributes.

Step 5 — Rendering Asynchronously with react-helmet-async

As brought up here by @mxstbr from Spectrum, React Helmet works synchronously which can potentially lead to issues on the server, especially with streaming.

A fork of React Helmet comes to the rescue: react-helmet-async.

  • npm install react-helmet-async@1.0.7

The API is the same, with the exception that a HelmetProvider needs to wrap the component tree on both the client and the server:

import Helmet, { HelmetProvider } from 'react-helmet-async';

function App() {
  return (
    <HelmetProvider>
      <div className="App">
        <Helmet>
          <title>App Title</title>
          <meta name="description" content="App Description" />
          <meta name="theme-color" content="#008f68" />
        </Helmet>
      </div>
    /HelmetProvider>
  );
}

More information on the intent and usage of React Helmet Async is available on the announcement post on the New York Times Open blog.

Conclusion

In this article, you explored the functionality of React Helmet in a React application. Particularly how it works well with server-side rendering for promoting SEO and social media integrations.

Here is a great reference of everything that can go into a document’s head by @joshbuchea.

If you’d like to learn more about React, take a look at our How To Code in React.js series, or check out our React topic page for exercises and programming projects.

Creative Commons License