422

I'd like to display a title in <AppBar /> that is somehow passed in from the current route.

In React Router v4, how would <AppBar /> be able to get the current route passed into it's title prop?

  <Router basename='/app'>
    <main>
      <Menu active={menu} close={this.closeMenu} />
      <Overlay active={menu} onClick={this.closeMenu} />
      <AppBar handleMenuIcon={this.handleMenuIcon} title='Test' />
      <Route path='/customers' component={Customers} />
    </main>
  </Router>

Is there a way to pass a custom title from a custom prop on <Route />?

1

10 Answers 10

511

In the 5.1 release of react-router there is a hook called useLocation, which returns the current location object. This might useful any time you need to know the current URL.

import { useLocation } from 'react-router-dom'

function HeaderView() {
  const location = useLocation();
  console.log(location.pathname);
  return <span>Path : {location.pathname}</span>
}

7
  • 68
    Please note this can only be used inside the Router DOM (i.e. chid components, not in the class / functional component where the Router is used). It may be obvious but not to a newbie like me:-) I was getting all the time the error "useContext is undefined" Commented May 23, 2020 at 22:58
  • 1
    also this will not work if a router redirect was used. this will read the path before the redirect
    – Sonic Soul
    Commented Jun 12, 2020 at 13:16
  • 3
    why not make location a const instead of a let since we know it won't change in this context? Commented Sep 18, 2020 at 16:14
  • 3
    They specifically asked for "React Router v4", not v5.
    – eriegz
    Commented Mar 17, 2022 at 15:59
  • 3
    @eriegz that's true but this is also the first Google result when searching for "Get current path name react router" so it's a very good thing that this answer is shown at the top
    – ICW
    Commented Nov 29, 2022 at 16:03
252

In react router 4 the current route is in - this.props.location.pathname. Just get this.props and verify. If you still do not see location.pathname then you should use the decorator withRouter.

This might look something like this:

import {withRouter} from 'react-router-dom';

const SomeComponent = withRouter(props => <MyComponent {...props}/>);

class MyComponent extends React.Component {
  SomeMethod () {
    const {pathname} = this.props.location;
  }
}
3
  • 14
    please note that this is not always true: with react-router4 , if your component is rendered on a higher level respect to some nested routes (which extends the path later) the location.pathname inside WithRouter will be different from window.location.pathname
    – maioman
    Commented Sep 16, 2017 at 13:09
  • 4
    How do we get it programmatically outside of a React component?
    – trusktr
    Commented Mar 7, 2019 at 2:53
  • 2
    This solution doesn't provide how to use these props in the component holding the <Router> itself.
    – freesoul
    Commented Nov 26, 2020 at 13:22
91

If you are using react's templates, where the end of your react file looks like this: export default SomeComponent you need to use the higher-order component (often referred to as an "HOC"), withRouter.

First, you'll need to import withRouter like so:

import {withRouter} from 'react-router-dom';

Next, you'll want to use withRouter. You can do this by change your component's export. It's likely you want to change from export default ComponentName to export default withRouter(ComponentName).

Then you can get the route (and other information) from props. Specifically, location, match, and history. The code to spit out the pathname would be:

console.log(this.props.location.pathname);

A good writeup with additional information is available here: https://reacttraining.com/react-router/core/guides/philosophy

1
  • But how do you get the complete url?
    – Trect
    Commented Dec 25, 2019 at 15:47
84

There's a hook called useLocation in react-router v5, no need for HOC or other stuff, it's very succinctly and convenient.

import { useLocation } from 'react-router-dom';

const ExampleComponent: React.FC = () => {
  const location = useLocation();  

  return (
    <Router basename='/app'>
      <main>
        <AppBar handleMenuIcon={this.handleMenuIcon} title={location.pathname} />
      </main>
    </Router>
  );
}
3
  • 1
    This answer should be rated much higher. Using the hook is so much easier and intuitive than these other solutions (if on RR v5)
    – BrDaHa
    Commented Mar 6, 2020 at 23:34
  • 1
    This is the current answer as of RR v5
    – BradStell
    Commented Jul 27, 2020 at 22:28
  • Great answer. I used this hook and useEeffect to reset my current page tab indicator value based on the pathname. Commented Apr 3, 2023 at 14:21
37

Here is a solution using history Read more

import { createBrowserHistory } from "history";

const history = createBrowserHistory()

inside Router

<Router>
   {history.location.pathname}
</Router>
2
  • 5
    For those of us on the react functional path, this answer makes the most sense. Those this.props.... whatever is just noise to our ears.
    – KhoPhi
    Commented Nov 25, 2019 at 15:03
  • This is the only solution that worked directly inside <Router></Router> tags, without a child component or using the document/window location directly.
    – freesoul
    Commented Nov 26, 2020 at 14:06
36

Has Con Posidielov said, the current route is present in this.props.location.pathname.

But if you want to match a more specific field like a key (or a name), you may use matchPath to find the original route reference.

import { matchPath } from `react-router`

const routes = [{
  key: 'page1'
  exact: true,
  path: '/page1/:someparam/',
  component: Page1,
},
{
  exact: true,
  key: 'page2',
  path: '/page2',
  component: Page2,
},
]

const currentRoute = routes.find(
  route => matchPath(this.props.location.pathname, route)
)

console.log(`My current route key is : ${currentRoute.key}`)
2
  • I have been able to use this method with v6, changing it to matchPath(route.path, this.props.location.pathname) as explained there
    – Walid
    Commented Feb 11, 2022 at 21:24
  • Use matchPath(route, this.props.location.pathname) to match the whole route definition
    – Tires
    Commented Jan 15, 2023 at 10:51
12

I think the author's of React Router (v4) just added that withRouter HOC to appease certain users. However, I believe the better approach is to just use render prop and make a simple PropsRoute component that passes those props. This is easier to test as you it doesn't "connect" the component like withRouter does. Have a bunch of nested components wrapped in withRouter and it's not going to be fun. Another benefit is you can also use this pass through whatever props you want to the Route. Here's the simple example using render prop. (pretty much the exact example from their website https://reacttraining.com/react-router/web/api/Route/render-func) (src/components/routes/props-route)

import React from 'react';
import { Route } from 'react-router';

export const PropsRoute = ({ component: Component, ...props }) => (
  <Route
    { ...props }
    render={ renderProps => (<Component { ...renderProps } { ...props } />) }
  />
);

export default PropsRoute;

usage: (notice to get the route params (match.params) you can just use this component and those will be passed for you)

import React from 'react';
import PropsRoute from 'src/components/routes/props-route';

export const someComponent = props => (<PropsRoute component={ Profile } />);

also notice that you could pass whatever extra props you want this way too

<PropsRoute isFetching={ isFetchingProfile } title="User Profile" component={ Profile } />
1
  • 4
    Is there any way we could turn this solution into a codepen? I want to use the more correct solution but I really don't understand how to implement.
    – user9844377
    Commented Apr 19, 2019 at 0:24
5

Add

import {withRouter} from 'react-router-dom';

Then change your component export

export default withRouter(ComponentName)

Then you can access the route directly within the component itself (without touching anything else in your project) using:

window.location.pathname

Tested March 2020 with: "version": "5.1.2"

1
  • 3
    Not sure about this one. Sure, it's giving the current pathname, but that doesn't change if I navigate to a new page.
    – alex
    Commented Apr 5, 2020 at 22:22
2

React Router Version 6

<Link to="/myuser?page=10#myHash">User</Link>

Use useLocation hook to get location object
const location = useLocation();

console.log('hash', location.hash); // #myHash
console.log('pathname', location.pathname); // /myuser
console.log('search', location.search); // ?page=10
0

1. First Warp App Component

// index.js

import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <BrowserRouter>
       <App />
    </BrowserRouter>
  </React.StrictMode>
);

2. Import useLocation Hook and get path name

// App.js

import {Routes, useLocation  } from "react-router-dom";

function App() {
  const location = useLocation();

  // Get current path
  const path = location.pathname;

  return (
      <>
       <Routes>
         <Components currentPath={path} />
       </Routes>
      </>
  );
}

location.pathname returns path name, use it as required.

Not the answer you're looking for? Browse other questions tagged or ask your own question.