React Router 6 路由参数

5
我正在尝试使用最新的 v6 版本设置一些 React Router 路由。我希望有一个类似于 rest 的页面层次结构,并且能够轻松地解析出 ID,特别是在路径中具有两个级别的 ID。
我遇到了一个问题,那就是如何使用 React Router 的范例正确解析出 URL 中的 ID。我可以使用 `window.location.pathname` 自己解析 URL 或使用类似于 2003 年的库进行解析,但肯定有更 React 的方法。
这是 URL 的基本期望结构:
/collection/          (all collections) 
/collection/123       (collection 123)
/collection/123/abc   (collection 123, subgroup abc)
/collection/123/all   (special handler, collection 123, all subgroups)

似乎我可以使用useParams(),但当我在界面中 console.log 它时,它似乎并不是非常有用或结构化。请看下面的示例。 是否应该有更好的方法来提取路由中指定的:id:groupId而不仅仅是一个 "*" 属性,我最终仍然需要自己解析它。我希望有一个"id"和"groupId"属性,但也许我方法错了。
// 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> 

编辑:根据下面的解决方案,这个路由结构符合我的需求。我不想在App.tsx中使用subroutes中的element属性,因为事情会变得更加复杂,我想保持App.tsx的轻量化。但是,删除element属性可以正常工作。然后,我只需要在屏幕中使用useParams()来访问所有参数,就像我最初需要的那样。

// 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 />}

1个回答

6
useParams钩子只返回当前Routes组件范围内的路由参数。
例如,如果路径为"/collection/123/456",则:
  • CollectionScreen只能看到{*: "123/456"}

    其中*来自于父级CollectionScreen路由。

  • CollectionGroup可以看到{*: "123/456", id: "123", groupId: "456"}

    其中*来自于父级CollectionScreen路由,idgroupId来自于子级CollectionGroup组件。

CollectionScreen无法查看其下方的路由参数,因为它正在呈现一个Routes组件,该组件有效地“阻止”了其下面的参数。对路由的小改进可以使CollectionScreen能够看到其下方的路由参数。

Edit react-router-6-route-params

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>

集合屏幕

const params = useParams();

console.log("CollectionScreen", params);

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

编辑react-router-6-route-params(分支)

现在,所有路由组件都可以看到相同的params对象。

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

2
这解释得很好。将子路由移动到App中是最好的方法,以便在需要参数访问的屏幕中获得它。我稍微调整了一下,以保持App之外的重活。请参见我上面的编辑。 - Miro
@Miro 哦,我明白了...这很棒。 - Drew Reese

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接