Is it possible to retrieve the unresolved path (dashboard/:companyId) of the currently active route?
Every hook/utility I tested only returns dashboard/abc.
My specific usecase:
I have a global (app-wide) company picker which should replace the companyId regardless of the current route.
So my idea would be to retrieve the unresolved route + params. Then check if there's a companyId and if so, resolve it with the new companyId.
Or is there a better solution for this?
const params = useParams();
const unresolvedRoute = use???(); // -> 'dashboard/:companyId'
if(params.companyId) {
const newCompany = 'xyz';
const newPath = generatePath(unresolvedRoute, { companyId: newCompany });
}
Should work for any route which contains a :companyId
/dashboard/company1 -> /dashboard/company
/dashboard/company1/details -> /dashboard/company2/details
/settings/company1 -> /settings/company2
There's not any "native" RRDv6 way really to get the pattern that was used, but I think you could solve this in a couple basic ways.
Use the matchPath utility function and an array of path patterns that can be matched and find/return the matching path pattern. Iterate the array of path patterns and return the one with a non-null match object.
import {
...
matchPath as matchPathBase,
useLocation,
useNavigate,
generatePath,
...
} from "react-router-dom";
const matchPath = (patterns, pathname) =>
[patterns].flat().find((pattern) => matchPathBase(pattern, pathname));
...
const { pathname } = useLocation();
const navigate = useNavigate();
const pattern = matchPath(
[
"/dashboard/:companyId",
"/dashboard/:companyId/details",
"/settings/:companyId"
],
pathname
);
React.useEffect(() => {
if (pattern) {
navigate(generatePath(pattern, { companyId }), { replace: true });
}
}, [companyId, navigate, pattern]);
Use the useMatches hook to return an array of matches and access the one with a defined handle that was provided to the route you want to get the pattern for. Use a Data router and add a handle prop object with a pattern property to each route you want to access a pattern for, then use the useMatches hook to find the match entry with a defined handle property (i.e. non-null match objects will have it).
import {
...
useNavigate,
generatePath,
useMatches,
...
} from "react-router-dom";
...
const navigate = useNavigate();
const matches = useMatches();
const [companyId, setCompanyId] = React.useState("123");
const { pattern } = matches.find((match) => match.handle)?.handle || {};
React.useEffect(() => {
if (pattern) {
navigate(generatePath(pattern, { companyId }), { replace: true });
}
}, [companyId, navigate, pattern]);
import {
createBrowserRouter,
RouterProvider
} from "react-router-dom";
const router = createBrowserRouter([
{
path: "/",
element: <Layout />,
children: [
{
path: "/dashboard",
children: [
{
path: ":companyId",
children: [
{
index: true,
element: <CompanyDashboard />,
handle: {
pattern: "/dashboard/:companyId"
}
},
{
path: "details",
element: <CompanyDetails />,
handle: {
pattern: "/dashboard/:companyId/details"
}
}
]
}
]
},
{
path: "/settings",
children: [
{
path: ":companyId",
children: [
{
index: true,
element: <SettingsDashboard />,
handle: {
pattern: "/settings/:companyId"
}
}
]
}
]
}
]
}
]);
...
<RouterProvider router={router} />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With