Home > front end >  react router 6 route params
react router 6 route params

Time:02-03

I am trying to set up some react router routes, using the newest v6 specifically. What I'd like to do is have a website with a rest-like hierarchy of pages, and be able to parse out the IDs easily. Specifically with two level of IDs on the path.

I'm having trouble with how I'm supposed to properly parse out the IDs from the url using react router paradigms. I could just use window.location.pathname and parse it myself or with a lib like it was 2003, but theres got to be a more react way to do it.

Here is the basic desired structure of urls:

/collection/          (all collections) 
/collection/123       (collection 123)
/collection/123/abc   (collection 123, subgroup abc)
/collection/123/all   (special handler, collection 123, all subgroups)

It seems I can use useParams(), however when I console.log that within my Screen it does not seem very helpful or structured at all. See below.

Should there be a better way to pull out the :id or :groupId specified in the routes? Instead of just one property for "*" that I still end up needing to parse myself anyway. I was hoping for a "id" and "groupId" property, but maybe I'm approaching it wrong.

// App.tsx
<BrowserRouter>
  <Routes>
    <Route path="/collection/*" element={<CollectionScreen />} />
  </Routes>
</BrowserRouter>
// CollectionScreen.tsx
const params = useParams()

console.log(params);
// {*: ''}        // path:  /collection
// {*: '123'}     // path:  /collection/123
// {*: '123/abc'} // path:  /collection/123/abc
 
...
 
<Routes>
  <Route path=":id/*" element={<Collection />} />
  <Route path=":id/all" element={<CollectionAll />} />
  <Route path=":id/:groupId" element={<CollectionGroup />} />
</Routes> 

EDIT: Based on solution below, this route structure does what I need. I didn't want to use the element in the subroutes in my App.tsx as things are a little more complicated and I want to keep App.tsx light. Removing the element property however works fine. I then just use useParams() in the Screen to access all the params as I originally needed.

// App.tsx
<Route path="/collection/*" element={<CollectionsScreen />}>
  <Route path=":id/*" />
  <Route path=":id/all" />
  <Route path=":id/:groupId" />
</Route>

// CollectionScreen.tsx
const params = useParams<{ id?: string; groupId?: string }>();
const { id, groupId } = params;

...

// simplified here, but easy access to id/groupId here is helpful
{!id && <Collection />}
{id && groupId && groupId === "all" && <CollectionAll />}
{id && groupId && groupId !== "all" && <CollectionGroup />}

CodePudding user response:

The useParams hook only returns the route params within the current Routes component scope.

For example, if the path is "/collection/123/456" then:

  • CollectionScreen sees {*: "123/456"}

    Where the * is from the parent CollectionScreen route.

  • CollectionGroup sees {*: "123/456", id: "123", groupId: "456"}

    Where the * is from the parent CollectionScreen route and id and groupId from the child CollectionGroup component.

Edit react-router-6-route-params

The CollectionScreen can't see route params further down because it is rendering a Routes component which effectively "gates" the params below it. A small refactor of the routes can allow CollectionScreen to see the route params routes below it.

App

<BrowserRouter>
  <Routes>
    <Route path="/collection/*">
      <Route path=":id" element={<CollectionScreen />}>
        <Route index element={<Collection />} />
        <Route path="all" element={<CollectionAll />} />
        <Route path=":groupId" element={<CollectionGroup />} />
      </Route>
    </Route>
  </Routes>
</BrowserRouter>

CollectionScreen

const params = useParams();

console.log("CollectionScreen", params);

return (
  <>
    ...
    <Outlet />
  </>
);

Edit react-router-6-route-params (forked)

Now all routed components see the same params object.

CollectionScreen {*: "123/456", id: "123", groupId: "456"}
CollectionGroup {*: "123/456", id: "123", groupId: "456"}
  •  Tags:  
  • Related