1

I'm looking for a way to reliably update a dynamic param in a URL with React Router 5.

My webpage has a global select component that allows to switch between different organizations and the URL can have multiple IDs in it.

The URL may look something like this https://www.baseurl.com/organization/:orgId/site/:siteId/user/:userId

So I need to change the :orgId param when the select value changes. Does React Router 5 provide a good way to do that (useLocation and useParams doesn't seem to have an API for that) or should I manipulate the URL string manually in such case?

Oleksandr Fomin
  • 2,005
  • 5
  • 25
  • 47

2 Answers2

1

You may be able to use the useParams hook and combine it with the generatePath utility function.

Example:

import { generatePath, useParams } from 'react-router-dom';

...

const params = useParams(); // { orgId, siteId, userId }

...

const path = generatePath(
  "/organization/:orgId/site/:siteId/user/:userId",
  {
    ...params,       // <-- shallow copy in the existing param values
    orgId: newOrgId, // <-- override the specific param values from state/etc
  },
);

Use the computed path variable in history.replace or as a Link component target.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • But how do I get the current URL (which could be anything) in such format "/organization/:orgId/site/:siteId/user/:userId", so that I can pass the all the IDs there? – Oleksandr Fomin Dec 14 '22 at 08:19
  • @OleksandrFomin Wouldn't that be the currently matched route? The component gets the ids from the `useParams` hook. Why wouldn't this component doing the org selection *not* know where it's being rendered? I took the route path definition from your post. Maybe I've misunderstood your scenario? – Drew Reese Dec 14 '22 at 08:21
  • yes, but the URL I can get from `useLocation` hook would have the actual IDs in it, so the `generatePath` function wouldn't know what to update – Oleksandr Fomin Dec 14 '22 at 08:31
  • @OleksandrFomin FWIW I don't think the `useLocation` hook is useful here since it yields the `pathname` when you want the `path` string that has the route path parameters you want to update. Maybe it would clearer what you are trying to work with if you could edit your post to include a [mcve] that includes the route you are working with and the component code trying to update a path parameter. – Drew Reese Dec 14 '22 at 08:35
  • The `path` string is something that I'd been struggling to retrieve. It seems to work now with `getRoutePath` function from this reply https://stackoverflow.com/a/70754791/13288420 combined with your solution. Thank you very much! – Oleksandr Fomin Dec 14 '22 at 08:57
  • @OleksandrFomin I see. Is it the case then that you *don't* actually have a defined dynamic route path, i.e. a route path with defined parameters, and that you sort of really *are* left with a bit of string manipulation? In any case, glad to help. Cheers. – Drew Reese Dec 14 '22 at 09:04
0

useNavigate provides a way to somehow do it but I think you have to create a function that manually handles the URL params.

// import useNavigate
import {useNavigate} from 'react-router-dom';

export default function App() {
  const navigate = useNavigate();

  const handleClick = () => {
    // navigate programmatically
    navigate({pathname: '/about', search: '?query=abc&page=25'});
  };

  return (
    <div>
      <button onClick={handleClick}>Navigate to About</button>
    </div>
  );
}
Ken Labso
  • 885
  • 9
  • 13