234

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>
1
  • 1
    Did my answer help? Commented Jan 20, 2022 at 10:23

12 Answers 12

326

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.

Sign up to request clarification or add additional context in comments.

10 Comments

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).
How do I set the exact attribute for a single path?
@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.
@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!).
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.
|
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.

5 Comments

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.
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ábioPaiva yeah I still haven't figured out how to put an arbitrary regex in the route
put it in as a string <Route path="/(new|edit)/user/:id?" ... />
not working with path={`/(${ROUTES.HOME}|${ROUTES.HOME_1})/`}
62

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.

4 Comments

Don't forget the key prop.
note this would cause (undesired...?) remounts when switching from paths (eg /home => /users in that example)
Indeed! The desirability probably depends on your use case and your components. If you don't want to remount, using regexp as indicated in my edit might work better.
Also, don't forget to remove exact if added.
26

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

4 Comments

Really?? Wtf…..
@Delice react-router-dom love to change their code to make us modify ours on each version update
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.
Correction: {['home', 'users', 'widgets'].map ...
8

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.

4 Comments

It works! but I am receiveing a Warning: Failed prop type: Invalid prop path supplied to Route.
@AzizStark You are right, it is not a correct answer. It is better you use <Route path={["/home", "/users", "/widgets"]} component={Home} /> as the solution.
What is this single-pipe syntax for strings? Cannot find it anywhere.
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)
6

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

<Routes>
  {['path1', 'path2'].map((path) => (
            <Route key={--> you should use some unique key <--} 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

9 Comments

@Nathan I am sorry, but I don't think so.
Ok np, but now we are using V6 which is also in your title
And for v6 this is not working
This worked fine for me in v6
A reminder If my edit won't get accepted-don't forget about key={index} (you can add index as a second parameter to the map method).
|
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>

Comments

3

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

Comments

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

Comments

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

1 Comment

This answer is no longer correct as path now accepts an array of string. See this answer.
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];
  }, []);

Comments

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>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.