215

I am using the same component for three different routes:

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

Is there anyway to combine it, to be like:

<Router>
    <Route path=["/home", "/users", "/widgets"] component={Home} />
</Router>
Ben Smith
  • 19,589
  • 6
  • 65
  • 93
Chetan Garg
  • 2,167
  • 2
  • 9
  • 3

12 Answers12

312

As of react-router v4.4.0-beta.4, and officially in v5.0.0, you can now specify an array of paths which resolve to a component e.g.

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

Each path in the array is a regular expression string.

The documentation for this approach can be found here.

Update for React Router v6

React Router v6 no longer allows an array of paths to be passed as a Route property. Instead you can make use of the useRoutes (see here for documentation) React hook to achieve the same behaviour:

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>
  );

You can see an extended example of this code working here.

The key take away from this answer is:

The useRoutes hook is the functional equivalent of <Routes>, but it uses JavaScript objects instead of <Route> elements to define your routes.

Ben Smith
  • 19,589
  • 6
  • 65
  • 93
  • 7
    I believe this is the best answer. @Cameron 's answer doesn't support full regexp feature anyways (at least I wasn't able to do it). – Christopher Regner Jan 23 '19 at 05:44
  • 4
    How do I set the `exact` attribute for a single path? – JulianSoto Apr 21 '19 at 03:45
  • 2
    @JulianSoto Create a Route to a component with one single path along with the exact path. You can then create another Route to the same component with an array of paths without the exact attribute. – Ben Smith Apr 21 '19 at 22:08
  • I can't `yarn upgrade` from 4.3 to 4.4. Is it officially released? – ndtreviv May 22 '19 at 10:09
  • @ndtreviv Looking at the react router change log I can see the feature was rolled out in v4.4.0 Beta 4. I'd recommend upgrading to the latest version, which at the time of writing this is v5.5.0. You can do this running "yarn upgrade react-router --latest" – Ben Smith May 23 '19 at 09:29
  • This doesn't seem to work anymore since v6, see answers below for alternatives – PdevG Jan 13 '22 at 11:04
  • 1
    @PdevG Thanks for making me aware of this. I've updated my answer with the recommend approach for v6 (and it's a different approach to the answers elsewhere in this thread!). – Ben Smith Jan 13 '22 at 13:58
  • Do you happen to know how one passes the same props to multiple elements without having to duplicate the props? That was clear from the array but not so much from the hook. Honestly the hook seems like a distinct step backwards as far as clarity of code is concerned. – Grant Curell Oct 29 '22 at 11:50
  • Hey @GrantCurell. You could use a map like I have done in this forked version of the code from my answer https://stackblitz.com/edit/github-dphbxg-rq961a?file=src%2FApp.tsx. In that example I'm using the same instance of the Home component, though you could do the same in the answer I gave above, but map is slightly less verbose. TBH Im not sure if I like this new hook in React Router, Im just accepting it and working with it! – Ben Smith Oct 31 '22 at 23:37
  • for v6, I recommend going with @bas answer. It doesn't violate the dry principle. Just don't forget to add index/key as is shown in Christopher Chiche example. – Fiddle Freak Nov 27 '22 at 05:05
136

At least with react-router v4 the path can be a regular expression string, so you can do something like this:

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

As you can see it's a bit verbose so if your component/route is simple like this it's probably not worth it.

And of course if this actually comes up often you could always create a wrapping component that takes in an array paths parameter, which does the regex or .map logic reusably.

primaryobjects
  • 35
  • 1
  • 2
  • 9
Cameron
  • 2,276
  • 2
  • 15
  • 12
  • 5
    Great idea @Cameron. I found it useful to modify it a bit to match only paths which begin with one of the groups: `/^\/(home|users|widgets)/` Now, `/widgets` will match, but `/dashboard/widgets` won't match. – Towler May 10 '17 at 17:48
  • 4
    Should be great, but for now the type regex is not valid on prop-types validation: `Warning: Failed prop type: Invalid prop `path` of type `regexp` supplied to `Route`, expected `string`.` – Fábio Paiva May 26 '17 at 12:20
  • @FábioPaiva yeah I still haven't figured out how to put an arbitrary regex in the route – Atav32 Feb 15 '18 at 18:13
  • 1
    put it in as a string `` – medv Jul 27 '18 at 17:32
  • 2
    not working with ```path={`/(${ROUTES.HOME}|${ROUTES.HOME_1})/`}``` – Murtaza Hussain May 21 '20 at 08:18
57

I don't think it is if you use a version of React Router lower than v4.

You can use a map as you would do with any other JSX component though:

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

EDIT

You can also use a regex for the path in react-router v4 as long as it's supported by path-to-regexp. See @Cameron's answer for more info.

Christopher Chiche
  • 15,075
  • 9
  • 59
  • 98
19

As of react router v6 they removed the option for regex and according to the type definition it is again path: string. Currently you would have to spell each path out again or use a map for convenience:

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

See also https://reactrouter.com/docs/en/v6/upgrading/v5#note-on-route-path-patterns

bas
  • 822
  • 10
  • 20
  • 4
    Really?? Wtf….. – Delice Jan 09 '22 at 16:38
  • @Delice react-router-dom love to change their code to make us modify ours on each version update – Warface Jan 10 '22 at 19:11
  • 1
    Apparently it is so they can actually parse and rank the paths better, so you can do `/card/new` and `/card/:cardId` and it will automatically choose the best fitting option. Which is of course a lot harder (if not impossible) to do if regexps are involved. – bas Jan 11 '22 at 11:07
  • 1
    Correction: `{['home', 'users', 'widgets'].map` ... – ElwoodP Aug 23 '22 at 15:17
9

As of react-route-dom v5.1.2 you can pass multiple path as below

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

And obvoiusly you need to import Home jsx file on top.

Abhishek
  • 648
  • 7
  • 8
  • 2
    It works! but I am receiveing a Warning: Failed prop type: Invalid prop `path` supplied to `Route`. – AzizStark Nov 04 '20 at 16:35
  • 12
    @AzizStark You are right, it is not a correct answer. It is better you use `` as the solution. – MJBZA Feb 04 '21 at 07:01
  • 1
    What is this single-pipe syntax for strings? Cannot find it anywhere. – Michal Kurz Feb 18 '21 at 11:58
  • That syntax can't work. Bitwise-or between strings returns 0. I suspect a regexp with alternatives was intended — but for that `|` chars should be inside the string, not operators between strings (and see other answers about regexps no longer being supported in v6) – Beni Cherniavsky-Paskin Apr 13 '23 at 17:48
3

Other option: use route prefix. /pages for example. You will get

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

And then resolve it in a detailed way inside the Home component.

<Router>
  <Route path="/pages/" component={Home} />
</Router>
arturtr
  • 1,115
  • 9
  • 18
3

With react-router v6, you can do like this:

<Routes>
  {['path1', 'path2'].map((path) => (
            <Route path={path} element={<SomeComponent />} />
  ))}
</Routes>

react-router docs says:

React Router v6 uses a simplified path format. <Route path> in v6 supports only 2 kinds of placeholders: dynamic :id-style params and * wildcards.

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

SandroMarques
  • 6,070
  • 1
  • 41
  • 46
1

if need add few routes from path

In APP add basic routes, like

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

here routed /dashboard path and call Dashboard component

then, in Dashboard component add few exact routes, like

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

here routed exact path, "/" mean "/dashboard"

/dashboard

/dashboard/user

/dashboard/role

1

Here's an example that works with React Router v6. It uses a helper function to abstract away mapping the paths to Route components. This helps keep the routes easy/intuitive to read and allows for easily mixing in MultiRoutes with regular Routes.

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>
  );
}

Zachary Duvall
  • 304
  • 1
  • 9
0

As per React Router docs the proptype 'path' is of type string .So there is no way you could pass an array as props to the Route Component.

If your intention is to only change route you can use the same component for different route no issues with that

Vijaykrish93
  • 150
  • 8
  • 1
    This answer is no longer correct as path now accepts an array of string. See this [answer](https://stackoverflow.com/a/53074599/203371). – Ben Smith Nov 05 '18 at 16:15
0

here is a little function to transform your custom routes with a paths prop to multiple standard routes supported by react-router v6, with path prop:

const normalizeRoutes = (routes) =>
  routes.reduce((acc, curr) => {
    const newRoute = curr.children
      ? { ...curr, children: normalizeRoutes(curr.children) }
      : curr;
    if (newRoute.paths) {
      return [
        ...acc,
        ...newRoute.paths.map((path) => {
          const { paths, ...rest } = newRoute;
          return { ...rest, path };
        })
      ];
    }
    return [...acc, newRoute];
  }, []);
LIIT
  • 496
  • 6
  • 16
0

react-router-dom no longer supports regexp in path, an alternative is to save the component in a variable and use that as the component for many routes.

let home= <Home />

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

return <Routes>
        <Route path="/home" element={home} />
        <Route path="/users" element={home} />
        <Route path="/widgets" element={home} />
    </Routes>
Benten
  • 1,014
  • 12
  • 17