DEV Community

Cover image for 🛠️ Dynamic HTML Titles in React with NFL's Helmet
Jaken Herman
Jaken Herman

Posted on

🛠️ Dynamic HTML Titles in React with NFL's Helmet

This post was originally published on my website at jakenherman.com

Using React through create-react-app is great, but when we consider that it will create a single-page application,
we begin to realize that changing properties in the document head of our html file is seemingly not so easy to do - but that
could not be further from the truth.

react-helmet is a reusable React component created by the NFL that can manage all of your changes to the document head, and it could
not be any simpler to use. It supports server-side rendering, and while this blog post is focused solely on changing HTML title tags,
react-helmet supports all valid head tags: title, base, meta, link, script, noscript, and style tags.

Let's quit talking about it and let's get into the code. First, create a new create-react-app application (named whatever you want) and open it up in your favorite
text editor (if you don't know how to do this, see the official create-react-app documentation

Now that you're in your project, delete the content from the pre-generated App.js file and replace the file with this:

import React from 'react';
import './App.css';

function App() {
  return (
    <div className="App">
      <h1>Hello World</h1>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

export default App;

Because we haven't made any modifications to the document title yet, the title within the tab should be "React App" by default. For this simple example, we're going to change the title based on a certain state within our App component. So, let's modify our functional component App to be a class component, and give it a state object that will hold the value we'd like our title to be:

import React from 'react';
import './App.css';

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      titleName: ''
    };
  }

  render () {
    return (
      <div className="App">
        <h1>Hello World</h1>
      </div>
    );
  }
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Now this will, of course, make no change to the title at this point (after all, we haven't even installed react-helmet yet!), but we're just setting up our project so when we get to the react-helmet part, it's much more satisfying. What I'd like to do is add an input field that allows the user to type in what they would like the title of the tab to be. So we're going to create an input and in the onChange of that input, we're going to update our state's titleName key's value to the value within the input, like so:

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      titleName: ''
    };
  }

  changeTitle(ev) {
    this.setState({
      titleName: ev.target.value
    });
  }

  render () {
    return (
      <div className="App">
        <h1>{this.state.titleName}</h1>
        <input onChange={this.changeTitle.bind(this)}></input>
      </div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

As you can see, I threw the this.state.titleName in an <h1> so we would have quick-and-easy proof that our state is being updated when the input's onChange event is fired.

Now, for the fun part. Open up your CLI and run the command:

  $ npm i react-helmet

  # or, using Yarn:
  $ yarn add react-helmet
Enter fullscreen mode Exit fullscreen mode

Now that react-helmet has been added to our project, we can add it to our <App /> component. To do this, we're first going to simply import the component, then just like we would in a typical HTML file, we're going to put the title information at the very top of our render() return, only instead of wrapping it in a <head> tag, we're going to wrap it in <Helmet> tags. And of course, for the <title>'s value, we're going to set it to this.state.titleName:

import React from 'react';
import { Helmet } from 'react-helmet';

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      titleName: ''
    };
  }

  changeTitle(ev) {
    this.setState({
      titleName: ev.target.value
    });
  }

  render () {
    return (
      <div className="App">
        <Helmet>
          <title>{this.state.titleName}</title>
        </Helmet>
        <input onChange={this.changeTitle.bind(this)}></input>
      </div>
    );
  }
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Now when changes are made to the input field, you can see the html title changes in the browser tab:
Dynamic Titles in React

<Helmet> can be used on any components, just keep in mind that child components will always override and helmet data passed through their parent components.

Thanks for reading, folks. Hope this taught you something.

Top comments (5)

Collapse
 
darksmile92 profile image
Robin Kretzschmar

Hey Jaken, do you know by chance how this way of generating the title affects SEO?
I don't do much SEO but in a recent side project I got aware of some pitfalls to look out to when building React sites and after reading your post I'm wondering if this could have a negative impact on how the search engines crawler interprets the site and also if this works in combination with Next and SSR?

Collapse
 
jakenherman profile image
Jaken Herman

That's a good question, one I hadn't actually considered. I'm using react-helmet for an internal application where SEO is not something our app is concerned with. I'd say to take a look at this Medium post for guidance (seems like it helps, not hurts!): medium.com/@prestonwallace/3-ways-...

Collapse
 
darksmile92 profile image
Robin Kretzschmar

Thank you for linking the medium post, seems like it does not hurt at all :)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.