How to Get the Current Route using React Router?

To get the current route using React Router, use the useLocation() hook in the functional component or the withRouter HOC (higher-order component) in the class component. Following the examples below to understand better.

Get the current route using React Router

Functional Component

The useLocation() hook is only available with react-router v5 (or higher). It returns some information about the current route. Before using this hook, wrap your root component (usually the App component) in the BrowserRouter component in the index.jsx file.

import React from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';

const container = document.getElementById('root');
const root = createRoot(container);

root.render(
  <Router>
    <App />
  </Router>
);

The hook returns a location object. The object contains some properties related to the current route, e.g., when the url is:

http://localhost/about?name=John&age=13#fragment

The return object looks like this:

In which:

  • hash: a URL fragment identifier begins with a #.
  • key:  a unique string associated with this location. It may be used to safely store and retrieve data in another storage API, like localStorage. Note: This value is always “default” on the initial location.
  • pathname: a URL pathname begins with a “/“.
  • search: a URL search string begins with a “?“.
  • state: a value of arbitrary data associated with this location.

If you get an error “useLocation() may be used only in the context of a Router component”, please read this article.

Let’s create an example showing an active route with the useLocation() hook.

First, we will config the nested routes in the App.jsx component:

function App() {
  return (
    <Routes>
      <Route path='/' element={<Layout />}>
        <Route index element={<Home />} />
        <Route path='users' element={<Users />} />
        <Route path='posts' element={<Posts />} />
      </Route>
    </Routes>
  );
}

The root route “Layout” will render the child routes, e.g., when the path = “/users“. The component tree will be:

<Layout>
  <Users></Users>
</Layout>

Note that the child route with the “index” prop will be rendered if no route matches the path. E.g., when the path = “/sub“:

<Layout>
  <Home></Home>
</Layout>

The Layout.jsx component:

function Layout() {
  return <Outlet />;
}

Remember to include the “Outlet” component because the child routes will not be displayed without it.

The MyCustomLink.jsx component:

function MyCustomLink({ children, path }) {
  let resolved = useResolvedPath(path);
  let location = useLocation();
  let isActive = resolved.pathname === location.pathname;

  return (
    <Link style={{ textDecoration: isActive ? 'underline' : 'none' }} to={path}>
      {children}
    </Link>
  );
}

We make a custom component wrap the Link component exported from the react-router library to make an active route. It takes in some props. The “children” prop will be the content of the component, and the “path” prop will be the destination path this link goes.

Here we use the useResolvedPath() hook. This hook resolves the pathname of the location in the given to value against the pathname of the current location. E.g., useResolvedPath(“/users”) will resolve the pathname location as “/users”. 

After resolving the custom pathname, we will compare it with the current location pathname. If it matches, then adds the active styles to the Link component.

Full code

import React from 'react';
import {
  Route,
  Link,
  Routes,
  useLocation,
  useResolvedPath,
  Outlet,
} from 'react-router-dom';

function App() {
  return (
    <div className='App'>
      <h1>Welcome to Learnshareit</h1>

      <nav>
        <ul>
          <li>
            <MyCustomLink path='/'>Home</MyCustomLink>
          </li>
          <li>
            <MyCustomLink path='/users'>Users</MyCustomLink>
          </li>
          <li>
            <MyCustomLink path='/posts'>Posts</MyCustomLink>
          </li>
        </ul>
      </nav>

      <Routes>
        <Route path='/' element={<Layout />}>
          <Route index element={<Home />} />
          <Route path='users' element={<Users />} />
          <Route path='posts' element={<Posts />} />
        </Route>
      </Routes>
    </div>
  );
}

function MyCustomLink({ children, path }) {
  let resolved = useResolvedPath(path);
  let location = useLocation();
  let isActive = resolved.pathname === location.pathname;

  return (
    <Link style={{ textDecoration: isActive ? 'underline' : 'none' }} to={path}>
      {children}
    </Link>
  );
}

function Layout() {
  return <Outlet />;
}

function Home() {
  return <h1>Home</h1>;
}

function Users() {
  return <h1>Favorite</h1>;
}

function Posts() {
  return <h1>Posts</h1>;
}

export default App;

Output

Class Component

The withRouter higher-order component lets you get the current route inside the class component. Note that the withRouter HOC has been removed from react-router v6. To use it, you have to download a lower version.

Example

import React from "react";
import { withRouter } from "react-router";

class Product extends React.Component {
   render() {
     return <div>You are now at {this.props.location.pathname}</div>;
   }
}

const ProductComponent = withRouter(Product);
export default ProductComponent;

In this case, we wrap the Product component with the withRouter() HOC.

Summary

This article is all about how to get the current route using React Router. You can use the useLocation() hook or the withRouter higher-order component. But you should use the useLocation() hook because, nowadays, most people use functional components, not class components. If you have any questions, please feel free to comment below.

Leave a Reply

Your email address will not be published. Required fields are marked *