Search code examples
reactjsreact-routerreact-router-dom

How to change title of the page of React-Router v6+ in history menu


There are a few questions like this on SO, but they are old and outdated and solutions don't work anymore

How can I change the title of the page so I don't have the same name in the History menu?

I can't find anything in the documentation I've tried:

<Link to="/home" title="Home"/>

but it doesn't work, I was looking at the code:

export interface LinkProps
  extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
  reloadDocument?: boolean;
  replace?: boolean;
  state?: any;
  to: To;
}

no title only state object.

The state is visible in the migration guide from v5 but it doesn't say what it is used for. I guess it's a history state object but it has nothing to do with title AFAIK.

Is there any way to have a title change in history? This seems that pretty common behavior for routing libraries that modify history titles.


Solution

  • 2024 update: useMatches()

    steinybot suggested a comprehensive solution with useMatches() - check it out https://stackoverflow.com/a/78184012/18817929

    Passing the title

    Given the React Router 6 code below:

    // App.jsx
    <Routes>
      <Route path="/home" element={<HomePage />} />
      <Route path="/about" element={<AboutPage />} />
    </Routes>
    
    

    It can be modified as follows to pass custom titles to corresponding components:

    // App.jsx
    <Routes>
      <Route path="/home" element={<HomePage title="Home"/>} />
      <Route path="/about" element={<AboutPage title="About" />} />
    </Routes>
    
    // HomePage.jsx
    export function HomePage(props) {
      useEffect(() => document.title = props.title, [])
      
      return <div>...</div>
    }
    

    and then the Link can be used as per usual.
    It can be further "prettified" by applying the HOC pattern - moving the title modification logic from each element component to the HOC.


    Parsing the URL

    Alternatively, it is possible to pre-define a route-to-title mapping and reactively update the document's title whenever the url changes:

    // App.jsx
    const titles = {
      '/home': 'Home',
      '/about': 'About',
    }
    
    function App() {
      const location = useLocation()
      useEffect(
        () => (document.title = titles[location.pathname] ?? 'Hello World'),
        [location],
      )
    
      return (
        <Routes>
          <Route path="/home" element={<HomePage />} />
          <Route path="/about" element={<AboutPage />} />
        </Routes>
      )
    }
    

    Although url params would require some additional parsing.