Is it possible to get the path pattern for the currently matched route? Example:
<Route
path=":state/:city*"
element={
<Page />
}
/>
// Page.jsx
function Page() {
...
// usePathPattern doesn't actually exist
const pathPattern = usePathPattern(); // pathPattern = ":state/:city*"
...
}
I know I can use useMatch to check if the current location matches a specific path pattern, but then the component has to know what the path pattern is.
You can use useLocation hook https://reactrouter.com/web/api/Hooks/uselocation.
In your case I see you are using params so useParams hook will give you access to the path pattern https://reactrouter.com/web/api/Hooks/useparams.
also
window.location.pathname
will give you the current url
import { useMatch, Route, Routes } from "react-router-dom";
<Routes>
<Route path="/" element={<Element1 match={useMatch("/")} />} >
<Route path=":id" element={<Element2 match={useMatch("/:id")} />} />
</Route>
</Routes>
From within the context of a Route you can get the path via several methods layed out in the docs.
My issue was slightly different in that I needed the path outside the context of the Route and came to the below solution that should also work for you:
import {
matchPath,
useLocation
} from "react-router-dom";
const routes = [ ':state/:city', ...otherRoutes ];
function usePathPattern() {
const { pathname } = useLocation();
return matchPath( pathname, routes )?.path;
}
It's not a direct answer to the question, but those, who found this question while trying to get the params from the match object, this can now be done with the useParams hook.
import { Route, Routes } from 'react-router-dom';
import { useParams } from 'react-router';
<Routes>
<Route path="/:id" element={<MyComponent />} />
</Routes>
...
function MyComponent() {
const { id } = useParams();
return <div>{id}</div>
}
Hope it's useful.
You cannot at this time. Here is the work around:
<Route path="/:state" element={<LocationView />} />
<Route path="/:state/:city*" element={<LocationView city />} />
I assume you're trying to render the same component under multiple paths. Instead of checking the path pattern, you can add a boolean prop to the component (in this case city) and check if the prop is true.
this is works for me easily
first of all import uselocation from react-router-dom
import { useLocation } from "react-router-dom"
then
const location = useLocation();
console.log(location.pathname);
I'm not sure if it resolves your use case fully but in my case I used combination of useLocation and useParams. Here is the code:
import React from 'react';
import { useLocation, useParams } from 'react-router-dom';
import type { Location, Params } from 'react-router-dom';
/**
* Function converts path like /user/123 to /user/:id
*/
const getRoutePath = (location: Location, params: Params): string => {
const { pathname } = location;
if (!Object.keys(params).length) {
return pathname; // we don't need to replace anything
}
let path = pathname;
Object.entries(params).forEach(([paramName, paramValue]) => {
if (paramValue) {
path = path.replace(paramValue, `:${paramName}`);
}
});
return path;
};
export const Foo = (): JSX.Element => {
const location = useLocation();
const params = useParams();
const path = getRoutePath(location, params);
(...)
};
This seems to work with what they actually export as of 6.2.1, however it uses a component they export as UNSAFE_
import { UNSAFE_RouteContext } from 'react-router-dom';
const reconstructPath = (matches) =>
matches
.map(({ route: { path } }) =>
path.endsWith('/*') ? path.slice(0, -1) : path ? path + '/' : ''
)
.join('');
const findLastNode = (node) =>
node.outlet ? findLastNode(node.outlet.props.value) : node;
const usePathPattern = () =>
reconstructPath(
findLastNode(React.useContext(UNSAFE_RouteContext)).matches
);
I made a custom hook useCurrentPath with react-router v6 to get the current route path, and it work for me
If the current pathname is /members/5566 I will get path /members/:id
import { matchRoutes, useLocation } from "react-router-dom"
const routes = [{ path: "/members/:id" }]
const useCurrentPath = () => {
const location = useLocation()
const [{ route }] = matchRoutes(routes, location)
return route.path
}
function MemberPage() {
const currentPath = useCurrentPath() // `/members/5566` -> `/members/:id`
return <></>
}
I wrote a custom hook for that purpose, since it doesn't seem to be supported oob right now:
Note: it's not thoroughly tested yet. So use with caution.
import { useLocation, useParams } from 'react-router';
export function useRoutePathPattern() {
const routeParams = useParams();
const location = useLocation();
let routePathPattern = location.pathname;
Object.keys(routeParams)
.filter((paramKey) => paramKey !== '*')
.forEach((paramKey) => {
const paramValue = routeParams[paramKey];
const regexMiddle = new RegExp(`\/${paramValue}\/`, 'g');
const regexEnd = new RegExp(`\/${paramValue}$`, 'g');
routePathPattern = routePathPattern.replaceAll(
regexMiddle,
`/:${paramKey}/`,
);
routePathPattern = routePathPattern.replaceAll(regexEnd, `/:${paramKey}`);
});
return routePathPattern;
}