反应路由器6路由参数

Mir*_*iro 5 reactjs react-router react-router-dom

我正在尝试设置一些反应路由器路由,专门使用最新的 v6。我想做的是拥有一个具有类似于休息的页面层次结构的网站,并且能够轻松解析出 ID。具体来说,路径上有两级 ID。

我在如何使用 React 路由器范例正确解析 url 中的 ID 时遇到了麻烦。我可以window.location.pathname自己使用和解析它,或者像 2003 年那样使用库,但必须有一种更具反应性的方法来做到这一点。

这是所需的基本 url 结构:

/collection/          (all collections) 
/collection/123       (collection 123)
/collection/123/abc   (collection 123, subgroup abc)
/collection/123/all   (special handler, collection 123, all subgroups)
Run Code Online (Sandbox Code Playgroud)

似乎我可以使用useParams(),但是当我console.log在屏幕中使用时,它似乎根本没有帮助或结构化。见下文。

是否应该有更好的方法来提取路线中的:id或指定的内容?:groupId无论如何,我最终仍然需要解析自己,而不只是“*”的一个属性。我希望有一个“id”和“groupId”属性,但也许我的做法是错误的。

// App.tsx
<BrowserRouter>
  <Routes>
    <Route path="/collection/*" element={<CollectionScreen />} />
  </Routes>
</BrowserRouter>
Run Code Online (Sandbox Code Playgroud)
// 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> 
Run Code Online (Sandbox Code Playgroud)

编辑:基于下面的解决方案,这个路由结构满足我的需要。我不想element在 App.tsx 的子路由中使用,因为事情有点复杂,而且我想让 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 />}

Run Code Online (Sandbox Code Playgroud)

Dre*_*ese 7

useParams钩子仅返回当前组件范围内的路由参数Routes

例如,如果路径是"/collection/123/456"

  • CollectionScreen看到{*: "123/456"}

    其中*来自父CollectionScreen路线。

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

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

编辑react-router-6-route-params

无法CollectionScreen看到进一步的路由参数,因为它正在渲染一个Routes组件,该组件有效地“门控”其下面的参数。对路由进行小的重构可以允许CollectionScreen查看其下面的路由参数路由。

应用程序

<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>
Run Code Online (Sandbox Code Playgroud)

收藏屏

const params = useParams();

console.log("CollectionScreen", params);

return (
  <>
    ...
    <Outlet />
  </>
);
Run Code Online (Sandbox Code Playgroud)

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

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

CollectionScreen {*: "123/456", id: "123", groupId: "456"}
CollectionGroup {*: "123/456", id: "123", groupId: "456"}
Run Code Online (Sandbox Code Playgroud)

  • 这很好地解释了这一点。将子路线移至应用程序是在我需要的屏幕中获取参数访问权限的最佳方法。我对其进行了一些调整,以将繁重的工作保留在 App 之外。请参阅上面我的编辑。 (2认同)