When using React Router v5, it was possible to get the path (pattern) for that route using useRouteMatch
.
const { path } = useRouteMatch();
React Router v6 offers a similar hook, useMatch
; however this expects to receive the pattern you want to match against.
I would use the React Router v5 hook to generate routes by combining the current path with known params.
As an example, if I am on the product page of an eCommerce application (let’s assume /en/product/:id
) and there are links to related products (/en/product/1
, /en/product/2
…etc), I would previously have been able to do:
const MyComponent = () => { const { path } = useRouteMatch(); return ( <div> <Link to={generatePath(path, { id: 1 })}>Related Product 1</Link> <Link to={generatePath(path, { id: 2 })}>Related Product 2</Link> </div> ); };
Since /en/product
comes from an API and is not declared anywhere in the code, I would want the URLs to be updated based on the current path. If the user is on /es/producto
, then the links would automatically be updated to /es/producto/1
.
I have seen solutions on SO where it was suggested to use matchRoutes
, however it feels highly inefficient, especially since the routes are dynamically generated from an external API.
const useCurrentPath = () => { const location = useLocation() const [{ route }] = matchRoutes(routes, location) return route.path }
I have created a small demo to illustrate how this used to work:
Advertisement
Answer
In react-router-dom@6
there is no replacement for the v5 useRouteMatch
hook. The links and routes no longer need to be concerned with the path
pattern so much as they can simply use relative routes and links. Instead of trying to access a route’s path pattern it can simply navigate relative to the currently matched path.
Example:
This navigates from "/route-a/2"
to "/route-a/2/../1"
or rather "/route-a/1"
.
const { pathname } = useLocation(); // navigate to sibling route path <Link to={`${pathname}/../${RELATED_ID}`}> Go to Nested Route {RELATED_ID} </Link>
Demo
Fullcode:
import { BrowserRouter, Link, Route, Routes, useParams, useLocation } from "react-router-dom"; import "./styles.css"; const RELATED_ID = 1; const MyComponent = ({ title }) => { const { pathname } = useLocation(); const { id } = useParams(); return ( <div> <h1> {title} {id} </h1> <pre>{pathname}</pre> {id && RELATED_ID && ( <Link to={`${pathname}/../${RELATED_ID}`}> Go to Nested Route {RELATED_ID} </Link> )} </div> ); }; export default function App() { return ( <div className="app"> <BrowserRouter> <nav> <Link to="/">Home</Link> <Link to="/route-a">Route A</Link> <Link to="/route-b">Route B</Link> <Link to="/route-a/1">Nested Route A1</Link> <Link to="/route-a/2">Nested Route A2</Link> <Link to="/route-b/1">Nested Route B1</Link> <Link to="/route-b/2">Nested Route B2</Link> </nav> <Routes> <Route path="/route-b" element={<MyComponent title="Nested Route" />} /> <Route path="/route-a" element={<MyComponent title="Nested Route" />} /> <Route path="/route-b/:id" element={<MyComponent title="Nested Route" />} /> <Route path="/route-a/:id" element={<MyComponent title="Nested Route" />} /> <Route path="/" /> </Routes> </BrowserRouter> </div> ); }