Monday, 28 May, 2018 UTC


Summary

React Helmet is a simple component that makes it easy to manage and dynamically set what’s in the document’s head section. For example, you can use React Helmet to set the title, description and meta tags for the document.
It comes-in especially handy when combined with server-side rendering because it allows to set meta tags that will be read by search engines and social media crawlers. This makes server-side rendering and React Helmet a dynamic duo for creating apps that are SEO and social media friendly.
Let’s go over the basic usage for React Helmet.
Installation & Basic Usage
First, simply install the component into your project using npm or Yarn:
$ npm i react-helmet # or, using Yarn: $ yarn add react-helmet 
Now you can use the component in your app by adding the elements that should go in the head of the document as children to the Helmet component:
import React, { Component } from 'react'; import { Helmet } from 'react-helmet'; // ... class App extends Component { render() { return ( <div> <Helmet> <title>Turbo Todo</title> <meta name="description" content="Todos on steroid!" /> <meta name="theme-color" content="#008f68" /> </Helmet> {/* ... */} </div> ); } } export default App; 
With this, if you open your browser’s elements inspector you’ll see the title and meta elements in the head section. This won’t be reflected in the page’s source code however if you don’t have server-side rendering in place. In other words, without the use of React Helmet on the server, your pages won’t have the extra elements in the head for search engine and social media crawlers to see.

Overwriting values

Components further down the tree can override values provided to the Helmet component on a higher level. For example, if our app has a ChildComponent like this:
ChildComponent.js
import React from 'react'; import { Helmet } from 'react-helmet'; export default () => { return ( <div> <Helmet> <title>Extreme Todoz</title> </Helmet> <h1>Child Component!</h1> </div> ) } 
import React, { Component } from 'react'; import { Helmet } from 'react-helmet'; import ChildComponent from './ChildComponent'; class App extends Component { render() { return ( <div> <Helmet> <title>Turbo Todo</title> <meta name="description" content="Todos on steroid!" /> <meta name="theme-color" content="#008f68" /> </Helmet> <ChildComponent /> </div> ); } } export default App; 
The resulting document title will be: Extreme Todoz, but the meta description and theme-color will still be in place because they are not overwritten.

Attributes for html & body

You can even include the html and body elements if you need to specify attributes for them. Here’s an example where we add a dark class name to the body element:
class App extends Component { render() { return ( <div> <Helmet> <title>Turbo Todo</title> <meta name="description" content="Todos on steroid!" /> <meta name="theme-color" content="#008f68" /> <body class="dark" /> </Helmet> {/* ... */} </div> ); } } 
Rendering on the Server
As we discussed, 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 basic React server-side rendered app setup in place, you can call Helmet’s renderStatic method right after calling ReactDOMServer’s renderToString or renderToStaticMarkup to get an instance with properties for the Helmet data:
index.js (server)
import React from 'react'; import { renderToString } from 'react-dom/server'; import express from 'express'; import App from './src/App'; const app = express(); // ... app.get('/*', (req, res) => { const app = renderToString(<App />); const helmet = Helmet.renderStatic(); res.send(formatHTML(app, helmet)); }); app.listen(3000); function formatHTML(appStr, helmet) { return ` <!DOCTYPE html> <html lang="en"> <head> ${helmet.title.toString()} ${helmet.meta.toString()} </head> <body> <div id="root"> ${ appStr } </div> <script src="./bundle.js"></script> </body> </html> ` } 
As you can see from this example, calling Helmet’s renderStatic returns an instance with properties like title and meta. You also have access to a bunch of other properties like link, script, noscript, style, htmlAttributes and bodyAttributes.
Async Rendering 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.
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 React, { Component } from 'react'; import Helmet, { HelmetProvider } from 'react-helmet-async'; // ... class App extends Component { render() { return ( <HelmetProvider> <Helmet> <title>Turbo Todo</title> <meta name="description" content="Todos on steroid!" /> <meta name="theme-color" content="#008f68" /> </Helmet> {/* ... */} </HelmetProvider> ); } } export default App; 
🤕 And that's it, React Helmet really makes it that easy! Here's a great reference of everything that can go into a document's head by @joshbuchea.