React Router中同一组件的多个路径名称

217

我正在为三个不同的路由使用相同的组件:

<Router>
    <Route path="/home" component={Home} />
    <Route path="/users" component={Home} />
    <Route path="/widgets" component={Home} />
</Router>

有没有办法将它们合并成这样:

<Router>
    <Route path=["/home", "/users", "/widgets"] component={Home} />
</Router>

1
我的回答有帮助吗? - Ben Smith
12个回答

314

从react-router v4.4.0-beta.4开始,在v5.0.0中正式支持,您现在可以指定一组解析为组件的路径,例如:

<Router>
    <Route path={["/home", "/users", "/widgets"]} component={Home} />
</Router>

数组中的每个路径都是一个正则表达式字符串。

有关此方法的文档可以在此处找到。

React Router v6 的更新

React Router v6不再允许将路径数组作为路由属性传递。 相反,您可以使用useRoutes(请参见此处的文档)React hook 来实现相同的行为:

import React from "react";
import {
  BrowserRouter as Router,
  useRoutes,
} from "react-router-dom";

const element = <Home />;
const App = () => 
 useRoutes(['/home', '/users', '/widgets'].map(path => ({path, element})));

const AppWrapper = () => (
    <Router>
      <App />
    </Router>
  );

您可以在此处查看此代码的扩展示例

本答案的关键是:

使用 useRoutes 钩子功能上等同于 <Routes>,但它使用 JavaScript 对象而不是 <Route> 元素来定义路由。


7
我相信这是最好的答案。@Cameron的答案无论如何都不支持完整的正则表达式功能(至少我没能做到)。 - Christopher Regner
4
我该如何为单个路径设置 exact 属性? - JulianSoto
2
@JulianSoto 创建一个只有一个路径的路由到组件,并指定确切的路径。然后,您可以创建另一个路由到同一组件,使用路径数组而不是确切属性。 - Ben Smith
1
@PdevG 感谢您让我意识到这一点。我已经更新了我的答案,提供了适用于v6的推荐方法(与本主题其他地方的答案不同!)。 - Ben Smith
1
文档更新链接:https://reactrouter.com/en/main/hooks/use-routes - flaudre
显示剩余8条评论

136

至少在 react-router v4 中,path 可以是一个正则表达式字符串,因此你可以像这样做:

至少在 react-router v4 中,path 可以是一个正则表达式字符串,因此你可以像这样做:

<Router>
    <Route path="/(home|users|widgets)/" component={Home} />
</Router>

如您所见,这有点啰嗦,如果您的component/route像这样简单,那么可能不值得这样做。

当然,如果这种情况经常出现,您可以创建一个包装组件,该组件接受一个数组paths参数,可重复使用正则表达式或.map逻辑。


5
很好的想法,@Cameron。我发现将其修改一下只匹配以以下任意一个组开头的路径更有用:/^\/(home|users|widgets)/ 现在, /widgets 会匹配成功,但是 /dashboard/widgets 将不匹配。 - Towler
4
目前来看应该很好,但是在prop-types验证中类型正则表达式无效:Warning: Failed prop type: Invalid prop 'path' of type 'regexp' supplied to 'Route', expected 'string'。 - Fábio Paiva
@FábioPaiva 嗯,我还没有想到如何将任意正则表达式放入路由中。 - Atav32
1
<Route path="/(new|edit)/user/:id?" ... /> - medv
2
无法使用path={`/(${ROUTES.HOME}|${ROUTES.HOME_1})/`} - Murtaza Hussain

59

如果你使用的是低于v4版本的React Router,我认为这不是一个问题。

然而,你可以像对待其他JSX组件一样使用map

<Router>
    {["/home", "/users", "/widgets"].map((path, index) => 
        <Route path={path} component={Home} key={index} />
    )}
</Router>

编辑

只要它被react-router v4支持的path-to-regexp,您还可以使用正则表达式来匹配路径。有关更多信息,请参见@Cameron的答案。


3
别忘了加上 key 属性。 - Neurotransmitter
11
注意,这会在切换路径时(例如,从 /home 切换到 /users)导致不期望的重新挂载。 - Hertzel Guinness
确实!可取性可能取决于您的用例和组件。如果您不想重新安装,使用我编辑中指示的正则表达式可能效果更好。 - Christopher Chiche
另外,不要忘记删除exact(如果已添加)。 - Kumar

21

从React Router v6开始,他们删除了正则表达式选项,并且根据类型定义,它再次变成了path: string。目前,您需要再次拼写每个路径,或者使用地图方便起见:

<Routes>
    {['home', 'users', 'widgets'].map(path => <Route path={path} element={<Home />} />)}
</Routes>

另请参见 https://reactrouter.com/docs/en/v6/upgrading/v5#note-on-route-path-patterns


5
真的吗?什么鬼…… - Delice
1
@Delice 喜欢修改他们的代码,导致我们在每次版本更新时都需要修改我们自己的代码。 - Warface
1
显然,这样做是为了更好地解析和排列路径,因此您可以使用/card/new/card/:cardId,它将自动选择最合适的选项。如果涉及正则表达式,则这当然会更加困难(如果不是不可能)。 - bas
1
更正: {['home', 'users', 'widgets'].map ... - ElwoodP

8

从react-route-dom v5.1.2版本开始,您可以按如下方式传递多个路径

 <Route path={"/home" | "/users" | "/widgets"} component={Home} />

显然,你需要在顶部导入Home jsx文件。


2
它可以工作!但是我收到了一个警告:Failed prop type: Invalid prop path supplied to Route. - AzizStark
12
@AzizStark 您是正确的,这不是一个正确的答案。更好的解决方案是使用 <Route path={["/home", "/users", "/widgets"]} component={Home} /> - MJBZA
1
这个单管道语法用于字符串是什么意思?我在任何地方都找不到它。 - Michal Kurz
那个语法不可行。字符串之间的按位或操作返回0。我怀疑正则表达式使用备选项,但是对于此目的,|字符应该在字符串内部,而不是在字符串之间作为运算符(并且请参见有关版本6中不再支持正则表达式的其他答案)。 - Beni Cherniavsky-Paskin

5
使用 React-Router v6,您可以这样做:
<Routes>
  {['path1', 'path2'].map((path) => (
            <Route path={path} element={<SomeComponent />} />
  ))}
</Routes>

React Router文档称:
React Router v6采用简化的路径格式。在v6中,<Route path>仅支持两种占位符:动态的:id风格参数和*通配符。
参考链接:https://reactrouter.com/docs/en/v6/upgrading/v5#note-on-route-path-patterns

这可以使用任何版本实现。路径属性接受一个数组,因此无需映射。 - Nathan
4
@Nathan,对不起,但我不这么认为。 - OndrejHj04
@OndrejHj04 请查看v5文档。Path支持string[]类型。 https://v5.reactrouter.com/web/api/Route/path-string-string - Nathan
2
好的,没问题。但是现在我们正在使用V6,这也在你的标题中提到了。 - OndrejHj04
5
对于v6版本,这并没有起作用。 - OndrejHj04
1
这在v6中对我很有效。 - Grant Curell

3

其他选项:使用路由前缀。例如/pages

  • /pages/home
  • /pages/users
  • /pages/widgets

然后在Home组件中详细解决它。

<Router>
  <Route path="/pages/" component={Home} />
</Router>

1
这是一个与React Router v6兼容的示例。它使用一个辅助函数来抽象出将路径映射到Route组件的过程。这有助于保持路由易于/直观地阅读,并允许轻松混合MultiRoute和常规Route
import { BrowserRouter, Route, Routes } from 'react-router-dom';

/**
 * For using the same JSX element with **multiple** paths
 * @param {JSXElement} el - JSX element
 * @param  {...string} paths - all paths that point to given JSX element
 * @returns `Route` elements
 */
function MultiRoute (el, ...paths) {
  return paths.map((p) => <Route key={p} element={el} path={p} />);
};

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route element={<LogIn />} path='/log-in' />
        <Route element={<SignUp />} path='/sign-up' />
        {MultiRoute(<Home />, '/home', '/users', '/widgets')}
        {MultiRoute(<Contact />, '/feedback', '/contact')}
      </Routes>
    </BrowserRouter>
  );
}


1

如果需要从路径中添加几个路由

在应用程序中添加基本路由,例如

<Routes>
  <Route path='/dashboard' element={<Dashboard/>} />
  <Route path='*' element={<NotFound/>} />
</Routes>

在这里,路由了 /dashboard 路径并调用了 Dashboard 组件。

然后,在 Dashboard 组件中添加一些确切的路由,例如:

return (
  <Routes>
    <Route exact path='/' element={<Client/>} />
    <Route exact path='/user' element={<One/>} />
    <Route exact path='/role' element={<Two/>} />
    <Route path='*' element={<NotFound/>} />
  </Routes>
)

这里指定了准确的路径,"/"表示 "/dashboard"

/dashboard

/dashboard/user

/dashboard/role


0
根据React Router文档,proptype 'path'是字符串类型。因此,您无法将数组作为props传递给Route组件。
如果您的意图仅是更改路由,则可以在不同路由上使用相同的组件,没有问题。

1
这个答案已经不正确了,因为现在path接受一个字符串数组。请参考这个答案 - Ben Smith

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