Is there a way to modify the page title with React-Router v4+?

Kevin Ghadyani picture Kevin Ghadyani · Sep 21, 2018 · Viewed 35.3k times · Source

I'm looking for a way to modify the page title when React-Router v4+ changes locations. I used to listen for a location change action in Redux and check that route against a metaData object.

When using React-Router v4+, there's no fixed routes list. In fact, various components around the site could use Route with the same path string. That means old method I used won't work anymore.

Is there a way I can update the page title by calling actions when certain major routes are changed or is there a better a better method to update the site's metadata?

Answer

phen0menon picture phen0menon · Jan 9, 2019

<Route /> components have render property. So you can modify the page title when location changes by declaring your routes like that:

<Route
  exact
  path="/"
  render={props => (
    <Page {...props} component={Index} title="Index Page" />
  )}
/>

<Route
  path="/about"
  render={props => (
    <Page {...props} component={About} title="About Page" />
  )}
/>

In Page component you can set the route title:

import React from "react"

/* 
 * Component which serves the purpose of a "root route component". 
 */
class Page extends React.Component {
  /**
   * Here, we define a react lifecycle method that gets executed each time 
   * our component is mounted to the DOM, which is exactly what we want in this case
   */
  componentDidMount() {
    document.title = this.props.title
  }
  
  /**
   * Here, we use a component prop to render 
   * a component, as specified in route configuration
   */
  render() {
    const PageComponent = this.props.component

    return (
      <PageComponent />
    )
  }
}

export default Page

Update 1 Aug 2019. This only works with react-router >= 4.x. Thanks to @supremebeing7

Updated answer using React Hooks:

You can specify the title of any route using the component below, which is built by using useEffect.

import { useEffect } from "react";

const Page = (props) => {
  useEffect(() => {
    document.title = props.title || "";
  }, [props.title]);
  return props.children;
};

export default Page;

And then use Page in the render prop of a route:

<Route
  path="/about"
  render={(props) => (
    <Page title="Index">
      <Index {...props} />
    </Page>
  )}
/>

<Route
  path="/profile"
  render={(props) => (
    <Page title="Profile">
      <Profile {...props} />
    </Page>
  )}
/>