主分支
分支
main (6.23.1)dev
版本
6.23.1v4/5.xv3.x
useResolvedPath

useResolvedPath

类型声明
declare function useResolvedPath(
  to: To,
  options?: { relative?: RelativeRoutingType }
): Path;

此钩子根据当前位置的路径名解析给定 to 值中的位置的 pathname

这在使用相对值构建链接时很有用。例如,查看 <NavLink> 的源代码,它在内部调用 useResolvedPath 来解析要链接到的页面的完整路径名。

有关更多信息,请参阅 resolvePath

通配符路径

useResolvedPath 的原始逻辑在处理通配符路径时表现不同,事后看来这是错误/有问题的行为。这个问题在 6.19.0 中得到了修复,但发现许多现有应用程序 依赖于这种行为,因此修复在 6.20.1 中被回滚,并在 6.21.0 中通过 future.v7_relativeSplatPath 未来标记 重新引入。这将在 React Router v7 中成为默认行为,因此建议您在方便的时候更新您的应用程序,以便为最终的 v7 升级做好准备。

需要注意的是,这是 React Router 中所有相对路由的基础,因此这也适用于以下相对路径代码流程

  • <Link to>
  • useNavigate()
  • useHref()
  • <Form action>
  • useSubmit()
  • 加载器和操作返回的相对路径 redirect 响应

没有启用标记的行为

当此标记未启用时,默认行为是在解析通配符路由 (*) 内的相对路径时,会忽略路径的通配符部分。因此,假设路由树如下所示

<BrowserRouter>
  <Routes>
    <Route path="/dashboard/*" element={<Dashboard />} />
  </Routes>
</BrowserRouter>

如果您当前位于 URL /dashboard/teams,则 Dashboard 组件中的 useResolvedPath("projects") 将解析为 /dashboard/projects,因为我们相对于其的“当前”位置将被视为 /dashboard (不包含“teams”通配符值)

这在“兄弟”通配符路由 (/dashboard/teams/dashboard/projects 等) 之间的路由中提供了一些便利,但它会导致其他不一致,例如

  • useResolvedPath(".") 不会再解析为该路由的当前位置,它实际上会将您从 /dashboard/teams “向上”解析到 /dashboard
  • 如果您将路由定义更改为使用动态参数 (<Route path="/dashboard/:widget">),则 Dashboard 组件中的任何解析路径都会中断,因为动态参数值不会像通配符值那样被忽略

然后,如果您将通配符路由定义为子路由,情况会更糟

<BrowserRouter>
  <Routes>
    <Route path="/dashboard">
      <Route path="*" element={<Dashboard />} />
    </Route>
  </Routes>
</BrowserRouter>
  • 现在,useResolvedPath(".")useResolvedPath("..")<Dashboard /> 中解析为完全相同的路径
  • 如果您使用的是数据路由并在通配符路由上定义了 action,那么您将在 <Dashboard> 中的 <Form> 提交时收到 405 错误,因为它们(默认情况下)提交到 ".",这将解析为父 /dashboard 路由,该路由没有 action

启用标记的行为

启用此标记后,此“错误”将得到修复,以便路径解析在所有路由类型中保持一致,并且 useResolvedPath(".") 始终解析为上下文路由的当前路径名。这包括任何动态参数或通配符参数值。

如果您想在通配符路由内的“兄弟”路由之间导航,建议您将通配符路由移到其自己的子路由中,并使用 useResolvedPath("../teams")useResolvedPath("../projects") 父级相对路径来导航到兄弟 /dashboard 路由。请注意,这里我们也使用 index,以便 URL /dashboard 也呈现 <Dashboard> 组件。

<BrowserRouter>
  <Routes>
    <Route path="/dashboard">
      <Route index path="*" element={<Dashboard />} />
    </Route>
  </Routes>
</BrowserRouter>